Linux-Fsdevel Archive on lore.kernel.org
 help / Atom feed
* [PATCH v5 00/17] fanotify: add support for more event types
@ 2019-01-10 17:04 Amir Goldstein
  2019-01-10 17:04 ` [PATCH v5 01/17] fsnotify: annotate directory entry modification events Amir Goldstein
                   ` (17 more replies)
  0 siblings, 18 replies; 34+ messages in thread
From: Amir Goldstein @ 2019-01-10 17:04 UTC (permalink / raw)
  To: Jan Kara; +Cc: Matthew Bobrowski, linux-fsdevel, linux-api

Jan,

This is the 5th revision of patch series to add support for filesystem
change monitoring to fanotify.

The complete work is available on fanotify_dirent-v5 branch [1] on github.

LTP tests by Matthew Bobrowski for FAN_REPORT_FID are available on
my LTP branch fanotify_fid [2]. A WIP test for dirent events is
available on my LTP branch fanotify_dirent [3].
Matthew Bobrowski is working on a proper test for dirent events and on
man pages for both FAN_REPORT_FID and dirent events (Thanks!).

The combined functionality of FAN_MARK_FILESYSTEM, FAN_REPORT_FID and
dirent modification events is demonstrated with a prototype of global
filesystem monitor based on inotify-tools [4].

Thanks,
Amir.

Changes since v4:
- Rebase on v5.0-rc1
- Address style review comments on v4
- info_len includes padding to info_hdr alignment
- handle caching of fsid correctly when inotify marks on object exist
- Report dirent events on subdirs only with FAN_ONDIR
- Report XXX_SELF events on directories only with FAN_ONDIR
- Do not merge dirent events on subdirs with dirent events on non subdirs

[1] https://github.com/amir73il/linux/commits/fanotify_dirent-v5
[2] https://github.com/amir73il/ltp/commits/fanotify_fid
[3] https://github.com/amir73il/ltp/commits/fanotify_dirent
[4] https://github.com/amir73il/inotify-tools/commits/fanotify_dirent

Amir Goldstein (17):
  fsnotify: annotate directory entry modification events
  fsnotify: remove dirent events from FS_EVENTS_POSS_ON_CHILD mask
  fsnotify: send all event types to super block marks
  fsnotify: move mask out of struct fsnotify_event
  fanotify: rename struct fanotify_{,perm_}event_info
  fanotify: open code fill_event_metadata()
  fanotify: encode file identifier for FAN_REPORT_FID
  fanotify: copy event fid info to user
  fanotify: enable FAN_REPORT_FID init flag
  fanotify: cache fsid in fsnotify_mark_connector
  vfs: add vfs_get_fsid() helper
  fanotify: use vfs_get_fsid() helper instead of vfs_statfs()
  fsnotify: report FS_ISDIR flag with MOVE_SELF and DELETE_SELF events
  fanotify: check FS_ISDIR flag instead of d_is_dir()
  fanotify: support events with data type FSNOTIFY_EVENT_INODE
  fanotify: add support for create/attrib/move/delete events
  fanotify: report FAN_ONDIR to listener with FAN_REPORT_FID

 fs/notify/fanotify/fanotify.c        | 229 +++++++++++++++++----
 fs/notify/fanotify/fanotify.h        | 105 ++++++++--
 fs/notify/fanotify/fanotify_user.c   | 288 +++++++++++++++++++--------
 fs/notify/fsnotify.c                 |  15 +-
 fs/notify/inotify/inotify.h          |   1 +
 fs/notify/inotify/inotify_fsnotify.c |  18 +-
 fs/notify/inotify/inotify_user.c     |   5 +-
 fs/notify/mark.c                     |  47 ++++-
 fs/notify/notification.c             |  22 +-
 fs/statfs.c                          |  14 ++
 include/linux/fanotify.h             |  26 ++-
 include/linux/fsnotify.h             |  94 +++++++--
 include/linux/fsnotify_backend.h     |  70 ++++---
 include/linux/statfs.h               |   3 +
 include/uapi/linux/fanotify.h        |  29 +++
 15 files changed, 753 insertions(+), 213 deletions(-)

-- 
2.17.1


^ permalink raw reply	[flat|nested] 34+ messages in thread

* [PATCH v5 01/17] fsnotify: annotate directory entry modification events
  2019-01-10 17:04 [PATCH v5 00/17] fanotify: add support for more event types Amir Goldstein
@ 2019-01-10 17:04 ` Amir Goldstein
  2019-02-06 14:14   ` Jan Kara
  2019-01-10 17:04 ` [PATCH v5 02/17] fsnotify: remove dirent events from FS_EVENTS_POSS_ON_CHILD mask Amir Goldstein
                   ` (16 subsequent siblings)
  17 siblings, 1 reply; 34+ messages in thread
From: Amir Goldstein @ 2019-01-10 17:04 UTC (permalink / raw)
  To: Jan Kara; +Cc: Matthew Bobrowski, linux-fsdevel

"dirent" events are referring to events that modify directory entries,
such as create,delete,rename. Those events should always be reported
on a watched directory, regardless if FS_EVENT_ON_CHILD is set
on the watch mask.

fsnotify_nameremove() and fsnotify_move() were modified to no longer
set the FS_EVENT_ON_CHILD event bit. This is a semantic change to
align with the "dirent" event definition. It has no effect on any
existing backend, because dnotify, inotify and audit always requets the
child events and fanotify does not get the delete,rename events.

The fsnotify_dirent() helper is used instead of fsnotify_parent() to
report a dirent event to dentry->d_parent without FS_EVENT_ON_CHILD
and regardless if parent has the FS_EVENT_ON_CHILD bit set.

Unlike fsnotify_parent(), fsnotify_dirent() assumes that dentry->d_name
and dentry->d_parent are stable. For fsnotify_create()/fsnotify_mkdir(),
this assumption is abviously correct. For fsnotify_nameremove(), it is
less trvial, so we use dget_parent() and take_dentry_name_snapshot() to
grab stable references.

Signed-off-by: Amir Goldstein <amir73il@gmail.com>
---
 include/linux/fsnotify.h | 68 ++++++++++++++++++++++++++++++++++------
 1 file changed, 59 insertions(+), 9 deletions(-)

diff --git a/include/linux/fsnotify.h b/include/linux/fsnotify.h
index 2ccb08cb5d6a..116907928c7f 100644
--- a/include/linux/fsnotify.h
+++ b/include/linux/fsnotify.h
@@ -17,8 +17,22 @@
 #include <linux/slab.h>
 #include <linux/bug.h>
 
+/*
+ * Notify this @dir inode about a change in the directory entry @dentry.
+ *
+ * Unlike fsnotify_parent(), the event will be reported regardless of the
+ * FS_EVENT_ON_CHILD mask on the parent inode.
+ */
+static inline int fsnotify_dirent(struct inode *dir, struct dentry *dentry,
+				  __u32 mask)
+{
+	return fsnotify(dir, mask, d_inode(dentry), FSNOTIFY_EVENT_INODE,
+			dentry->d_name.name, 0);
+}
+
 /* Notify this dentry's parent about a child's events. */
-static inline int fsnotify_parent(const struct path *path, struct dentry *dentry, __u32 mask)
+static inline int fsnotify_parent(const struct path *path,
+				  struct dentry *dentry, __u32 mask)
 {
 	if (!dentry)
 		dentry = path->dentry;
@@ -85,8 +99,8 @@ static inline void fsnotify_move(struct inode *old_dir, struct inode *new_dir,
 {
 	struct inode *source = moved->d_inode;
 	u32 fs_cookie = fsnotify_get_cookie();
-	__u32 old_dir_mask = (FS_EVENT_ON_CHILD | FS_MOVED_FROM);
-	__u32 new_dir_mask = (FS_EVENT_ON_CHILD | FS_MOVED_TO);
+	__u32 old_dir_mask = FS_MOVED_FROM;
+	__u32 new_dir_mask = FS_MOVED_TO;
 	const unsigned char *new_name = moved->d_name.name;
 
 	if (old_dir == new_dir)
@@ -128,15 +142,54 @@ static inline void fsnotify_vfsmount_delete(struct vfsmount *mnt)
 
 /*
  * fsnotify_nameremove - a filename was removed from a directory
+ *
+ * Called from d_delete() and nfs_complete_sillyrename().
+ * The latter is called from nfs client ->unlink() ->rmdir() ->rename()
+ * under parent vfs inode lock.
+ *
+ * Most filesystems call d_delete() from ->unlink() ->rmdir() ->rename()
+ * ops under parent vfs inode lock.
+ *
+ * Some pseudo filesystems call d_delete() without parent inode lock.
+ * Those filesystems have no ->rename() op and they do not call
+ * d_move() directly, so d_parent and d_name are stable by definition.
+ * Examples: devpts, efivarfs, rpc_pipefs, functionfs.
+ *
+ * Some clustered filesystems call d_delete() on remote nodes, not under
+ * vfs parent inode lock, but they use cluster distributed locks on local
+ * and remote nodes. Those filesystems call d_delete() under their cluster
+ * lock. Examples:
+ * - in ceph_fill_trace() under CEPH_MDS_R_PARENT_LOCKED
+ * - in ocfs2_dentry_convert_worker() under ocfs2_dentry_lock
+ * But those filesystems also call d_move() under the same cluster lock
+ * (i.e. FS_RENAME_DOES_D_MOVE), so d_parent and d_name are also stable.
+ *
+ * However, to be on the safe side and be reselient to future callers
+ * and out of tree users of d_delete(), we do not assume that d_parent and
+ * d_name are stable and we use dget_parent() and take_dentry_name_snapshot()
+ * to grab stable references.
  */
 static inline void fsnotify_nameremove(struct dentry *dentry, int isdir)
 {
+	struct dentry *parent;
+	struct name_snapshot name;
 	__u32 mask = FS_DELETE;
 
+	/* d_delete() of pseudo inode? (e.g. __ns_get_path() playing tricks) */
+	if (IS_ROOT(dentry))
+		return;
+
 	if (isdir)
 		mask |= FS_ISDIR;
 
-	fsnotify_parent(NULL, dentry, mask);
+	parent = dget_parent(dentry);
+	take_dentry_name_snapshot(&name, dentry);
+
+	fsnotify(d_inode(parent), mask, d_inode(dentry), FSNOTIFY_EVENT_INODE,
+		 name.name, 0);
+
+	release_dentry_name_snapshot(&name);
+	dput(parent);
 }
 
 /*
@@ -155,7 +208,7 @@ static inline void fsnotify_create(struct inode *inode, struct dentry *dentry)
 {
 	audit_inode_child(inode, dentry, AUDIT_TYPE_CHILD_CREATE);
 
-	fsnotify(inode, FS_CREATE, dentry->d_inode, FSNOTIFY_EVENT_INODE, dentry->d_name.name, 0);
+	fsnotify_dirent(inode, dentry, FS_CREATE);
 }
 
 /*
@@ -176,12 +229,9 @@ static inline void fsnotify_link(struct inode *dir, struct inode *inode, struct
  */
 static inline void fsnotify_mkdir(struct inode *inode, struct dentry *dentry)
 {
-	__u32 mask = (FS_CREATE | FS_ISDIR);
-	struct inode *d_inode = dentry->d_inode;
-
 	audit_inode_child(inode, dentry, AUDIT_TYPE_CHILD_CREATE);
 
-	fsnotify(inode, mask, d_inode, FSNOTIFY_EVENT_INODE, dentry->d_name.name, 0);
+	fsnotify_dirent(inode, dentry, FS_CREATE | FS_ISDIR);
 }
 
 /*
-- 
2.17.1


^ permalink raw reply	[flat|nested] 34+ messages in thread

* [PATCH v5 02/17] fsnotify: remove dirent events from FS_EVENTS_POSS_ON_CHILD mask
  2019-01-10 17:04 [PATCH v5 00/17] fanotify: add support for more event types Amir Goldstein
  2019-01-10 17:04 ` [PATCH v5 01/17] fsnotify: annotate directory entry modification events Amir Goldstein
@ 2019-01-10 17:04 ` Amir Goldstein
  2019-01-10 17:04 ` [PATCH v5 03/17] fsnotify: send all event types to super block marks Amir Goldstein
                   ` (15 subsequent siblings)
  17 siblings, 0 replies; 34+ messages in thread
From: Amir Goldstein @ 2019-01-10 17:04 UTC (permalink / raw)
  To: Jan Kara; +Cc: Matthew Bobrowski, linux-fsdevel

"dirent" events are referring to events that modify directory entries,
such as create,delete,rename. Those events are always be reported
on a watched directory, regardless if FS_EVENT_ON_CHILD is set
on the watch mask.

ALL_FSNOTIFY_DIRENT_EVENTS defines all the dirent event types and
those event types are removed from FS_EVENTS_POSS_ON_CHILD.

That means for a directory with an inotify watch and only dirent
events in the mask (i.e. create,delete,move), all children dentries
will no longer have the DCACHE_FSNOTIFY_PARENT_WATCHED flag set.
This will allow all events that happen on children to be optimized
away in __fsnotify_parent() without the need to dereference
child->d_parent->d_inode->i_fsnotify_mask.

Since the dirent events are never repoted via __fsnotify_parent(),
this results in no change of logic, but only an optimization.

Signed-off-by: Amir Goldstein <amir73il@gmail.com>
---
 include/linux/fsnotify_backend.h | 36 +++++++++++++++++++-------------
 1 file changed, 21 insertions(+), 15 deletions(-)

diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h
index 7639774e7475..7f195d43efaf 100644
--- a/include/linux/fsnotify_backend.h
+++ b/include/linux/fsnotify_backend.h
@@ -59,27 +59,33 @@
  * dnotify and inotify. */
 #define FS_EVENT_ON_CHILD	0x08000000
 
-/* This is a list of all events that may get sent to a parernt based on fs event
- * happening to inodes inside that directory */
-#define FS_EVENTS_POSS_ON_CHILD   (FS_ACCESS | FS_MODIFY | FS_ATTRIB |\
-				   FS_CLOSE_WRITE | FS_CLOSE_NOWRITE | FS_OPEN |\
-				   FS_MOVED_FROM | FS_MOVED_TO | FS_CREATE |\
-				   FS_DELETE | FS_OPEN_PERM | FS_ACCESS_PERM | \
-				   FS_OPEN_EXEC | FS_OPEN_EXEC_PERM)
-
 #define FS_MOVE			(FS_MOVED_FROM | FS_MOVED_TO)
 
+/*
+ * Directory entry modification events - reported only to directory
+ * where entry is modified and not to a watching parent.
+ * The watching parent may get an FS_ATTRIB|FS_EVENT_ON_CHILD event
+ * when a directory entry inside a child subdir changes.
+ */
+#define ALL_FSNOTIFY_DIRENT_EVENTS	(FS_CREATE | FS_DELETE | FS_MOVE)
+
 #define ALL_FSNOTIFY_PERM_EVENTS (FS_OPEN_PERM | FS_ACCESS_PERM | \
 				  FS_OPEN_EXEC_PERM)
 
+/*
+ * This is a list of all events that may get sent to a parent based on fs event
+ * happening to inodes inside that directory.
+ */
+#define FS_EVENTS_POSS_ON_CHILD   (ALL_FSNOTIFY_PERM_EVENTS | \
+				   FS_ACCESS | FS_MODIFY | FS_ATTRIB | \
+				   FS_CLOSE_WRITE | FS_CLOSE_NOWRITE | \
+				   FS_OPEN | FS_OPEN_EXEC)
+
 /* Events that can be reported to backends */
-#define ALL_FSNOTIFY_EVENTS (FS_ACCESS | FS_MODIFY | FS_ATTRIB | \
-			     FS_CLOSE_WRITE | FS_CLOSE_NOWRITE | FS_OPEN | \
-			     FS_MOVED_FROM | FS_MOVED_TO | FS_CREATE | \
-			     FS_DELETE | FS_DELETE_SELF | FS_MOVE_SELF | \
-			     FS_UNMOUNT | FS_Q_OVERFLOW | FS_IN_IGNORED | \
-			     FS_OPEN_PERM | FS_ACCESS_PERM | FS_DN_RENAME | \
-			     FS_OPEN_EXEC | FS_OPEN_EXEC_PERM)
+#define ALL_FSNOTIFY_EVENTS (ALL_FSNOTIFY_DIRENT_EVENTS | \
+			     FS_EVENTS_POSS_ON_CHILD | \
+			     FS_DELETE_SELF | FS_MOVE_SELF | FS_DN_RENAME | \
+			     FS_UNMOUNT | FS_Q_OVERFLOW | FS_IN_IGNORED)
 
 /* Extra flags that may be reported with event or control handling of events */
 #define ALL_FSNOTIFY_FLAGS  (FS_EXCL_UNLINK | FS_ISDIR | FS_IN_ONESHOT | \
-- 
2.17.1


^ permalink raw reply	[flat|nested] 34+ messages in thread

* [PATCH v5 03/17] fsnotify: send all event types to super block marks
  2019-01-10 17:04 [PATCH v5 00/17] fanotify: add support for more event types Amir Goldstein
  2019-01-10 17:04 ` [PATCH v5 01/17] fsnotify: annotate directory entry modification events Amir Goldstein
  2019-01-10 17:04 ` [PATCH v5 02/17] fsnotify: remove dirent events from FS_EVENTS_POSS_ON_CHILD mask Amir Goldstein
@ 2019-01-10 17:04 ` Amir Goldstein
  2019-01-10 17:04 ` [PATCH v5 04/17] fsnotify: move mask out of struct fsnotify_event Amir Goldstein
                   ` (14 subsequent siblings)
  17 siblings, 0 replies; 34+ messages in thread
From: Amir Goldstein @ 2019-01-10 17:04 UTC (permalink / raw)
  To: Jan Kara; +Cc: Matthew Bobrowski, linux-fsdevel

So far, existence of super block marks was checked only on events with
data type FSNOTIFY_EVENT_PATH. Use the super block of the "to_tell" inode
to report the events of all event types to super block marks.

This change has no effect on current backends. Soon, this will allow
fanotify backend to receive all event types on a super block mark.

Signed-off-by: Amir Goldstein <amir73il@gmail.com>
---
 fs/notify/fsnotify.c | 15 +++++++--------
 1 file changed, 7 insertions(+), 8 deletions(-)

diff --git a/fs/notify/fsnotify.c b/fs/notify/fsnotify.c
index ecf09b6243d9..df06f3da166c 100644
--- a/fs/notify/fsnotify.c
+++ b/fs/notify/fsnotify.c
@@ -328,16 +328,15 @@ int fsnotify(struct inode *to_tell, __u32 mask, const void *data, int data_is,
 	     const unsigned char *file_name, u32 cookie)
 {
 	struct fsnotify_iter_info iter_info = {};
-	struct super_block *sb = NULL;
+	struct super_block *sb = to_tell->i_sb;
 	struct mount *mnt = NULL;
-	__u32 mnt_or_sb_mask = 0;
+	__u32 mnt_or_sb_mask = sb->s_fsnotify_mask;
 	int ret = 0;
 	__u32 test_mask = (mask & ALL_FSNOTIFY_EVENTS);
 
 	if (data_is == FSNOTIFY_EVENT_PATH) {
 		mnt = real_mount(((const struct path *)data)->mnt);
-		sb = mnt->mnt.mnt_sb;
-		mnt_or_sb_mask = mnt->mnt_fsnotify_mask | sb->s_fsnotify_mask;
+		mnt_or_sb_mask |= mnt->mnt_fsnotify_mask;
 	}
 	/* An event "on child" is not intended for a mount/sb mark */
 	if (mask & FS_EVENT_ON_CHILD)
@@ -350,8 +349,8 @@ int fsnotify(struct inode *to_tell, __u32 mask, const void *data, int data_is,
 	 * SRCU because we have no references to any objects and do not
 	 * need SRCU to keep them "alive".
 	 */
-	if (!to_tell->i_fsnotify_marks &&
-	    (!mnt || (!mnt->mnt_fsnotify_marks && !sb->s_fsnotify_marks)))
+	if (!to_tell->i_fsnotify_marks && !sb->s_fsnotify_marks &&
+	    (!mnt || !mnt->mnt_fsnotify_marks))
 		return 0;
 	/*
 	 * if this is a modify event we may need to clear the ignored masks
@@ -366,11 +365,11 @@ int fsnotify(struct inode *to_tell, __u32 mask, const void *data, int data_is,
 
 	iter_info.marks[FSNOTIFY_OBJ_TYPE_INODE] =
 		fsnotify_first_mark(&to_tell->i_fsnotify_marks);
+	iter_info.marks[FSNOTIFY_OBJ_TYPE_SB] =
+		fsnotify_first_mark(&sb->s_fsnotify_marks);
 	if (mnt) {
 		iter_info.marks[FSNOTIFY_OBJ_TYPE_VFSMOUNT] =
 			fsnotify_first_mark(&mnt->mnt_fsnotify_marks);
-		iter_info.marks[FSNOTIFY_OBJ_TYPE_SB] =
-			fsnotify_first_mark(&sb->s_fsnotify_marks);
 	}
 
 	/*
-- 
2.17.1


^ permalink raw reply	[flat|nested] 34+ messages in thread

* [PATCH v5 04/17] fsnotify: move mask out of struct fsnotify_event
  2019-01-10 17:04 [PATCH v5 00/17] fanotify: add support for more event types Amir Goldstein
                   ` (2 preceding siblings ...)
  2019-01-10 17:04 ` [PATCH v5 03/17] fsnotify: send all event types to super block marks Amir Goldstein
@ 2019-01-10 17:04 ` Amir Goldstein
  2019-01-10 17:04 ` [PATCH v5 05/17] fanotify: rename struct fanotify_{,perm_}event_info Amir Goldstein
                   ` (13 subsequent siblings)
  17 siblings, 0 replies; 34+ messages in thread
From: Amir Goldstein @ 2019-01-10 17:04 UTC (permalink / raw)
  To: Jan Kara; +Cc: Matthew Bobrowski, linux-fsdevel

Common fsnotify_event helpers have no need for the mask field.
It is only used by backend code, so move the field out of the
abstract fsnotify_event struct and into the concrete backend
event structs.

This change packs struct inotify_event_info better on 64bit
machine and will allow us to cram some more fields into
struct fanotify_event_info.

Signed-off-by: Amir Goldstein <amir73il@gmail.com>
---
 fs/notify/fanotify/fanotify.c        | 11 +++++++----
 fs/notify/fanotify/fanotify.h        |  1 +
 fs/notify/fanotify/fanotify_user.c   | 10 +++++-----
 fs/notify/inotify/inotify.h          |  1 +
 fs/notify/inotify/inotify_fsnotify.c |  9 +++++----
 fs/notify/inotify/inotify_user.c     |  5 +++--
 fs/notify/notification.c             | 22 +---------------------
 include/linux/fsnotify_backend.h     | 10 ++++++----
 8 files changed, 29 insertions(+), 40 deletions(-)

diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c
index 3723f3d18d20..98197802bbfb 100644
--- a/fs/notify/fanotify/fanotify.c
+++ b/fs/notify/fanotify/fanotify.c
@@ -36,20 +36,22 @@ static bool should_merge(struct fsnotify_event *old_fsn,
 static int fanotify_merge(struct list_head *list, struct fsnotify_event *event)
 {
 	struct fsnotify_event *test_event;
+	struct fanotify_event_info *new;
 
 	pr_debug("%s: list=%p event=%p\n", __func__, list, event);
+	new = FANOTIFY_E(event);
 
 	/*
 	 * Don't merge a permission event with any other event so that we know
 	 * the event structure we have created in fanotify_handle_event() is the
 	 * one we should check for permission response.
 	 */
-	if (fanotify_is_perm_event(event->mask))
+	if (fanotify_is_perm_event(new->mask))
 		return 0;
 
 	list_for_each_entry_reverse(test_event, list, list) {
 		if (should_merge(test_event, event)) {
-			test_event->mask |= event->mask;
+			FANOTIFY_E(test_event)->mask |= new->mask;
 			return 1;
 		}
 	}
@@ -173,7 +175,8 @@ struct fanotify_event_info *fanotify_alloc_event(struct fsnotify_group *group,
 	if (!event)
 		goto out;
 init: __maybe_unused
-	fsnotify_init_event(&event->fse, inode, mask);
+	fsnotify_init_event(&event->fse, inode);
+	event->mask = mask;
 	if (FAN_GROUP_FLAG(group, FAN_REPORT_TID))
 		event->pid = get_pid(task_pid(current));
 	else
@@ -280,7 +283,7 @@ static void fanotify_free_event(struct fsnotify_event *fsn_event)
 	event = FANOTIFY_E(fsn_event);
 	path_put(&event->path);
 	put_pid(event->pid);
-	if (fanotify_is_perm_event(fsn_event->mask)) {
+	if (fanotify_is_perm_event(event->mask)) {
 		kmem_cache_free(fanotify_perm_event_cachep,
 				FANOTIFY_PE(fsn_event));
 		return;
diff --git a/fs/notify/fanotify/fanotify.h b/fs/notify/fanotify/fanotify.h
index ea05b8a401e7..e630d787d4c3 100644
--- a/fs/notify/fanotify/fanotify.h
+++ b/fs/notify/fanotify/fanotify.h
@@ -14,6 +14,7 @@ extern struct kmem_cache *fanotify_perm_event_cachep;
  */
 struct fanotify_event_info {
 	struct fsnotify_event fse;
+	u32 mask;
 	/*
 	 * We hold ref to this path so it may be dereferenced at any point
 	 * during this object's lifetime
diff --git a/fs/notify/fanotify/fanotify_user.c b/fs/notify/fanotify/fanotify_user.c
index 9c870b0d2b56..dea47d07cc29 100644
--- a/fs/notify/fanotify/fanotify_user.c
+++ b/fs/notify/fanotify/fanotify_user.c
@@ -131,9 +131,9 @@ static int fill_event_metadata(struct fsnotify_group *group,
 	metadata->metadata_len = FAN_EVENT_METADATA_LEN;
 	metadata->vers = FANOTIFY_METADATA_VERSION;
 	metadata->reserved = 0;
-	metadata->mask = fsn_event->mask & FANOTIFY_OUTGOING_EVENTS;
+	metadata->mask = event->mask & FANOTIFY_OUTGOING_EVENTS;
 	metadata->pid = pid_vnr(event->pid);
-	if (unlikely(fsn_event->mask & FAN_Q_OVERFLOW))
+	if (unlikely(event->mask & FAN_Q_OVERFLOW))
 		metadata->fd = FAN_NOFD;
 	else {
 		metadata->fd = create_fd(group, event, file);
@@ -230,7 +230,7 @@ static ssize_t copy_event_to_user(struct fsnotify_group *group,
 			 fanotify_event_metadata.event_len))
 		goto out_close_fd;
 
-	if (fanotify_is_perm_event(event->mask))
+	if (fanotify_is_perm_event(FANOTIFY_E(event)->mask))
 		FANOTIFY_PE(event)->fd = fd;
 
 	if (fd != FAN_NOFD)
@@ -316,7 +316,7 @@ static ssize_t fanotify_read(struct file *file, char __user *buf,
 		 * Permission events get queued to wait for response.  Other
 		 * events can be destroyed now.
 		 */
-		if (!fanotify_is_perm_event(kevent->mask)) {
+		if (!fanotify_is_perm_event(FANOTIFY_E(kevent)->mask)) {
 			fsnotify_destroy_event(group, kevent);
 		} else {
 			if (ret <= 0) {
@@ -401,7 +401,7 @@ static int fanotify_release(struct inode *ignored, struct file *file)
 	 */
 	while (!fsnotify_notify_queue_is_empty(group)) {
 		fsn_event = fsnotify_remove_first_event(group);
-		if (!(fsn_event->mask & FANOTIFY_PERM_EVENTS)) {
+		if (!(FANOTIFY_E(fsn_event)->mask & FANOTIFY_PERM_EVENTS)) {
 			spin_unlock(&group->notification_lock);
 			fsnotify_destroy_event(group, fsn_event);
 			spin_lock(&group->notification_lock);
diff --git a/fs/notify/inotify/inotify.h b/fs/notify/inotify/inotify.h
index 7e4578d35b61..74ae60305189 100644
--- a/fs/notify/inotify/inotify.h
+++ b/fs/notify/inotify/inotify.h
@@ -5,6 +5,7 @@
 
 struct inotify_event_info {
 	struct fsnotify_event fse;
+	u32 mask;
 	int wd;
 	u32 sync_cookie;
 	int name_len;
diff --git a/fs/notify/inotify/inotify_fsnotify.c b/fs/notify/inotify/inotify_fsnotify.c
index f4184b4f3815..fe97299975f2 100644
--- a/fs/notify/inotify/inotify_fsnotify.c
+++ b/fs/notify/inotify/inotify_fsnotify.c
@@ -43,11 +43,11 @@ static bool event_compare(struct fsnotify_event *old_fsn,
 {
 	struct inotify_event_info *old, *new;
 
-	if (old_fsn->mask & FS_IN_IGNORED)
-		return false;
 	old = INOTIFY_E(old_fsn);
 	new = INOTIFY_E(new_fsn);
-	if ((old_fsn->mask == new_fsn->mask) &&
+	if (old->mask & FS_IN_IGNORED)
+		return false;
+	if ((old->mask == new->mask) &&
 	    (old_fsn->inode == new_fsn->inode) &&
 	    (old->name_len == new->name_len) &&
 	    (!old->name_len || !strcmp(old->name, new->name)))
@@ -114,7 +114,8 @@ int inotify_handle_event(struct fsnotify_group *group,
 	}
 
 	fsn_event = &event->fse;
-	fsnotify_init_event(fsn_event, inode, mask);
+	fsnotify_init_event(fsn_event, inode);
+	event->mask = mask;
 	event->wd = i_mark->wd;
 	event->sync_cookie = cookie;
 	event->name_len = len;
diff --git a/fs/notify/inotify/inotify_user.c b/fs/notify/inotify/inotify_user.c
index 105576daca4a..2cec820de151 100644
--- a/fs/notify/inotify/inotify_user.c
+++ b/fs/notify/inotify/inotify_user.c
@@ -189,7 +189,7 @@ static ssize_t copy_event_to_user(struct fsnotify_group *group,
 	 */
 	pad_name_len = round_event_name_len(fsn_event);
 	inotify_event.len = pad_name_len;
-	inotify_event.mask = inotify_mask_to_arg(fsn_event->mask);
+	inotify_event.mask = inotify_mask_to_arg(event->mask);
 	inotify_event.wd = event->wd;
 	inotify_event.cookie = event->sync_cookie;
 
@@ -634,7 +634,8 @@ static struct fsnotify_group *inotify_new_group(unsigned int max_events)
 		return ERR_PTR(-ENOMEM);
 	}
 	group->overflow_event = &oevent->fse;
-	fsnotify_init_event(group->overflow_event, NULL, FS_Q_OVERFLOW);
+	fsnotify_init_event(group->overflow_event, NULL);
+	oevent->mask = FS_Q_OVERFLOW;
 	oevent->wd = -1;
 	oevent->sync_cookie = 0;
 	oevent->name_len = 0;
diff --git a/fs/notify/notification.c b/fs/notify/notification.c
index 3c3e36745f59..027d5d5bb90e 100644
--- a/fs/notify/notification.c
+++ b/fs/notify/notification.c
@@ -71,7 +71,7 @@ void fsnotify_destroy_event(struct fsnotify_group *group,
 			    struct fsnotify_event *event)
 {
 	/* Overflow events are per-group and we don't want to free them */
-	if (!event || event->mask == FS_Q_OVERFLOW)
+	if (!event || event == group->overflow_event)
 		return;
 	/*
 	 * If the event is still queued, we have a problem... Do an unreliable
@@ -194,23 +194,3 @@ void fsnotify_flush_notify(struct fsnotify_group *group)
 	}
 	spin_unlock(&group->notification_lock);
 }
-
-/*
- * fsnotify_create_event - Allocate a new event which will be sent to each
- * group's handle_event function if the group was interested in this
- * particular event.
- *
- * @inode the inode which is supposed to receive the event (sometimes a
- *	parent of the inode to which the event happened.
- * @mask what actually happened.
- * @data pointer to the object which was actually affected
- * @data_type flag indication if the data is a file, path, inode, nothing...
- * @name the filename, if available
- */
-void fsnotify_init_event(struct fsnotify_event *event, struct inode *inode,
-			 u32 mask)
-{
-	INIT_LIST_HEAD(&event->list);
-	event->inode = inode;
-	event->mask = mask;
-}
diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h
index 7f195d43efaf..1e4b88bd1443 100644
--- a/include/linux/fsnotify_backend.h
+++ b/include/linux/fsnotify_backend.h
@@ -135,7 +135,6 @@ struct fsnotify_event {
 	struct list_head list;
 	/* inode may ONLY be dereferenced during handle_event(). */
 	struct inode *inode;	/* either the inode the event happened to or its parent */
-	u32 mask;		/* the type of access, bitwise OR for FS_* event types */
 };
 
 /*
@@ -485,9 +484,12 @@ extern void fsnotify_put_mark(struct fsnotify_mark *mark);
 extern void fsnotify_finish_user_wait(struct fsnotify_iter_info *iter_info);
 extern bool fsnotify_prepare_user_wait(struct fsnotify_iter_info *iter_info);
 
-/* put here because inotify does some weird stuff when destroying watches */
-extern void fsnotify_init_event(struct fsnotify_event *event,
-				struct inode *to_tell, u32 mask);
+static inline void fsnotify_init_event(struct fsnotify_event *event,
+				       struct inode *inode)
+{
+	INIT_LIST_HEAD(&event->list);
+	event->inode = inode;
+}
 
 #else
 
-- 
2.17.1


^ permalink raw reply	[flat|nested] 34+ messages in thread

* [PATCH v5 05/17] fanotify: rename struct fanotify_{,perm_}event_info
  2019-01-10 17:04 [PATCH v5 00/17] fanotify: add support for more event types Amir Goldstein
                   ` (3 preceding siblings ...)
  2019-01-10 17:04 ` [PATCH v5 04/17] fsnotify: move mask out of struct fsnotify_event Amir Goldstein
@ 2019-01-10 17:04 ` Amir Goldstein
  2019-01-10 17:04 ` [PATCH v5 06/17] fanotify: open code fill_event_metadata() Amir Goldstein
                   ` (12 subsequent siblings)
  17 siblings, 0 replies; 34+ messages in thread
From: Amir Goldstein @ 2019-01-10 17:04 UTC (permalink / raw)
  To: Jan Kara; +Cc: Matthew Bobrowski, linux-fsdevel

struct fanotify_event_info "inherits" from struct fsnotify_event and
therefore a more appropriate (and short) name for it is fanotify_event.
Same for struct fanotify_perm_event_info, which now "inherits" from
struct fanotify_event.

We plan to reuse the name struct fanotify_event_info for user visible
event info record format.

Signed-off-by: Amir Goldstein <amir73il@gmail.com>
---
 fs/notify/fanotify/fanotify.c      | 16 ++++++++--------
 fs/notify/fanotify/fanotify.h      | 16 ++++++++--------
 fs/notify/fanotify/fanotify_user.c | 20 ++++++++++----------
 3 files changed, 26 insertions(+), 26 deletions(-)

diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c
index 98197802bbfb..d8e3b6e50844 100644
--- a/fs/notify/fanotify/fanotify.c
+++ b/fs/notify/fanotify/fanotify.c
@@ -19,7 +19,7 @@
 static bool should_merge(struct fsnotify_event *old_fsn,
 			 struct fsnotify_event *new_fsn)
 {
-	struct fanotify_event_info *old, *new;
+	struct fanotify_event *old, *new;
 
 	pr_debug("%s: old=%p new=%p\n", __func__, old_fsn, new_fsn);
 	old = FANOTIFY_E(old_fsn);
@@ -36,7 +36,7 @@ static bool should_merge(struct fsnotify_event *old_fsn,
 static int fanotify_merge(struct list_head *list, struct fsnotify_event *event)
 {
 	struct fsnotify_event *test_event;
-	struct fanotify_event_info *new;
+	struct fanotify_event *new;
 
 	pr_debug("%s: list=%p event=%p\n", __func__, list, event);
 	new = FANOTIFY_E(event);
@@ -60,7 +60,7 @@ static int fanotify_merge(struct list_head *list, struct fsnotify_event *event)
 }
 
 static int fanotify_get_response(struct fsnotify_group *group,
-				 struct fanotify_perm_event_info *event,
+				 struct fanotify_perm_event *event,
 				 struct fsnotify_iter_info *iter_info)
 {
 	int ret;
@@ -143,11 +143,11 @@ static u32 fanotify_group_event_mask(struct fsnotify_iter_info *iter_info,
 		~marks_ignored_mask;
 }
 
-struct fanotify_event_info *fanotify_alloc_event(struct fsnotify_group *group,
+struct fanotify_event *fanotify_alloc_event(struct fsnotify_group *group,
 						 struct inode *inode, u32 mask,
 						 const struct path *path)
 {
-	struct fanotify_event_info *event = NULL;
+	struct fanotify_event *event = NULL;
 	gfp_t gfp = GFP_KERNEL_ACCOUNT;
 
 	/*
@@ -162,7 +162,7 @@ struct fanotify_event_info *fanotify_alloc_event(struct fsnotify_group *group,
 	memalloc_use_memcg(group->memcg);
 
 	if (fanotify_is_perm_event(mask)) {
-		struct fanotify_perm_event_info *pevent;
+		struct fanotify_perm_event *pevent;
 
 		pevent = kmem_cache_alloc(fanotify_perm_event_cachep, gfp);
 		if (!pevent)
@@ -200,7 +200,7 @@ static int fanotify_handle_event(struct fsnotify_group *group,
 				 struct fsnotify_iter_info *iter_info)
 {
 	int ret = 0;
-	struct fanotify_event_info *event;
+	struct fanotify_event *event;
 	struct fsnotify_event *fsn_event;
 
 	BUILD_BUG_ON(FAN_ACCESS != FS_ACCESS);
@@ -278,7 +278,7 @@ static void fanotify_free_group_priv(struct fsnotify_group *group)
 
 static void fanotify_free_event(struct fsnotify_event *fsn_event)
 {
-	struct fanotify_event_info *event;
+	struct fanotify_event *event;
 
 	event = FANOTIFY_E(fsn_event);
 	path_put(&event->path);
diff --git a/fs/notify/fanotify/fanotify.h b/fs/notify/fanotify/fanotify.h
index e630d787d4c3..898b5b2bc1c7 100644
--- a/fs/notify/fanotify/fanotify.h
+++ b/fs/notify/fanotify/fanotify.h
@@ -12,7 +12,7 @@ extern struct kmem_cache *fanotify_perm_event_cachep;
  * fanotify_handle_event() and freed when the information is retrieved by
  * userspace
  */
-struct fanotify_event_info {
+struct fanotify_event {
 	struct fsnotify_event fse;
 	u32 mask;
 	/*
@@ -30,16 +30,16 @@ struct fanotify_event_info {
  * group->notification_list to group->fanotify_data.access_list to wait for
  * user response.
  */
-struct fanotify_perm_event_info {
-	struct fanotify_event_info fae;
+struct fanotify_perm_event {
+	struct fanotify_event fae;
 	int response;	/* userspace answer to question */
 	int fd;		/* fd we passed to userspace for this event */
 };
 
-static inline struct fanotify_perm_event_info *
+static inline struct fanotify_perm_event *
 FANOTIFY_PE(struct fsnotify_event *fse)
 {
-	return container_of(fse, struct fanotify_perm_event_info, fae.fse);
+	return container_of(fse, struct fanotify_perm_event, fae.fse);
 }
 
 static inline bool fanotify_is_perm_event(u32 mask)
@@ -48,11 +48,11 @@ static inline bool fanotify_is_perm_event(u32 mask)
 		mask & FANOTIFY_PERM_EVENTS;
 }
 
-static inline struct fanotify_event_info *FANOTIFY_E(struct fsnotify_event *fse)
+static inline struct fanotify_event *FANOTIFY_E(struct fsnotify_event *fse)
 {
-	return container_of(fse, struct fanotify_event_info, fse);
+	return container_of(fse, struct fanotify_event, fse);
 }
 
-struct fanotify_event_info *fanotify_alloc_event(struct fsnotify_group *group,
+struct fanotify_event *fanotify_alloc_event(struct fsnotify_group *group,
 						 struct inode *inode, u32 mask,
 						 const struct path *path);
diff --git a/fs/notify/fanotify/fanotify_user.c b/fs/notify/fanotify/fanotify_user.c
index dea47d07cc29..55cd87b0cc26 100644
--- a/fs/notify/fanotify/fanotify_user.c
+++ b/fs/notify/fanotify/fanotify_user.c
@@ -73,7 +73,7 @@ static struct fsnotify_event *get_one_event(struct fsnotify_group *group,
 }
 
 static int create_fd(struct fsnotify_group *group,
-		     struct fanotify_event_info *event,
+		     struct fanotify_event *event,
 		     struct file **file)
 {
 	int client_fd;
@@ -120,13 +120,13 @@ static int fill_event_metadata(struct fsnotify_group *group,
 			       struct file **file)
 {
 	int ret = 0;
-	struct fanotify_event_info *event;
+	struct fanotify_event *event;
 
 	pr_debug("%s: group=%p metadata=%p event=%p\n", __func__,
 		 group, metadata, fsn_event);
 
 	*file = NULL;
-	event = container_of(fsn_event, struct fanotify_event_info, fse);
+	event = container_of(fsn_event, struct fanotify_event, fse);
 	metadata->event_len = FAN_EVENT_METADATA_LEN;
 	metadata->metadata_len = FAN_EVENT_METADATA_LEN;
 	metadata->vers = FANOTIFY_METADATA_VERSION;
@@ -144,10 +144,10 @@ static int fill_event_metadata(struct fsnotify_group *group,
 	return ret;
 }
 
-static struct fanotify_perm_event_info *dequeue_event(
+static struct fanotify_perm_event *dequeue_event(
 				struct fsnotify_group *group, int fd)
 {
-	struct fanotify_perm_event_info *event, *return_e = NULL;
+	struct fanotify_perm_event *event, *return_e = NULL;
 
 	spin_lock(&group->notification_lock);
 	list_for_each_entry(event, &group->fanotify_data.access_list,
@@ -169,7 +169,7 @@ static struct fanotify_perm_event_info *dequeue_event(
 static int process_access_response(struct fsnotify_group *group,
 				   struct fanotify_response *response_struct)
 {
-	struct fanotify_perm_event_info *event;
+	struct fanotify_perm_event *event;
 	int fd = response_struct->fd;
 	int response = response_struct->response;
 
@@ -370,7 +370,7 @@ static ssize_t fanotify_write(struct file *file, const char __user *buf, size_t
 static int fanotify_release(struct inode *ignored, struct file *file)
 {
 	struct fsnotify_group *group = file->private_data;
-	struct fanotify_perm_event_info *event, *next;
+	struct fanotify_perm_event *event, *next;
 	struct fsnotify_event *fsn_event;
 
 	/*
@@ -688,7 +688,7 @@ SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags)
 	struct fsnotify_group *group;
 	int f_flags, fd;
 	struct user_struct *user;
-	struct fanotify_event_info *oevent;
+	struct fanotify_event *oevent;
 
 	pr_debug("%s: flags=%x event_f_flags=%x\n",
 		 __func__, flags, event_f_flags);
@@ -955,10 +955,10 @@ static int __init fanotify_user_setup(void)
 
 	fanotify_mark_cache = KMEM_CACHE(fsnotify_mark,
 					 SLAB_PANIC|SLAB_ACCOUNT);
-	fanotify_event_cachep = KMEM_CACHE(fanotify_event_info, SLAB_PANIC);
+	fanotify_event_cachep = KMEM_CACHE(fanotify_event, SLAB_PANIC);
 	if (IS_ENABLED(CONFIG_FANOTIFY_ACCESS_PERMISSIONS)) {
 		fanotify_perm_event_cachep =
-			KMEM_CACHE(fanotify_perm_event_info, SLAB_PANIC);
+			KMEM_CACHE(fanotify_perm_event, SLAB_PANIC);
 	}
 
 	return 0;
-- 
2.17.1


^ permalink raw reply	[flat|nested] 34+ messages in thread

* [PATCH v5 06/17] fanotify: open code fill_event_metadata()
  2019-01-10 17:04 [PATCH v5 00/17] fanotify: add support for more event types Amir Goldstein
                   ` (4 preceding siblings ...)
  2019-01-10 17:04 ` [PATCH v5 05/17] fanotify: rename struct fanotify_{,perm_}event_info Amir Goldstein
@ 2019-01-10 17:04 ` Amir Goldstein
  2019-01-10 17:04 ` [PATCH v5 07/17] fanotify: encode file identifier for FAN_REPORT_FID Amir Goldstein
                   ` (11 subsequent siblings)
  17 siblings, 0 replies; 34+ messages in thread
From: Amir Goldstein @ 2019-01-10 17:04 UTC (permalink / raw)
  To: Jan Kara; +Cc: Matthew Bobrowski, linux-fsdevel

The helper is quite trivial and open coding it will make it easier
to implement copying event fid info to user.

Signed-off-by: Amir Goldstein <amir73il@gmail.com>
---
 fs/notify/fanotify/fanotify_user.c | 69 +++++++++++-------------------
 1 file changed, 26 insertions(+), 43 deletions(-)

diff --git a/fs/notify/fanotify/fanotify_user.c b/fs/notify/fanotify/fanotify_user.c
index 55cd87b0cc26..2f4901ac090c 100644
--- a/fs/notify/fanotify/fanotify_user.c
+++ b/fs/notify/fanotify/fanotify_user.c
@@ -114,36 +114,6 @@ static int create_fd(struct fsnotify_group *group,
 	return client_fd;
 }
 
-static int fill_event_metadata(struct fsnotify_group *group,
-			       struct fanotify_event_metadata *metadata,
-			       struct fsnotify_event *fsn_event,
-			       struct file **file)
-{
-	int ret = 0;
-	struct fanotify_event *event;
-
-	pr_debug("%s: group=%p metadata=%p event=%p\n", __func__,
-		 group, metadata, fsn_event);
-
-	*file = NULL;
-	event = container_of(fsn_event, struct fanotify_event, fse);
-	metadata->event_len = FAN_EVENT_METADATA_LEN;
-	metadata->metadata_len = FAN_EVENT_METADATA_LEN;
-	metadata->vers = FANOTIFY_METADATA_VERSION;
-	metadata->reserved = 0;
-	metadata->mask = event->mask & FANOTIFY_OUTGOING_EVENTS;
-	metadata->pid = pid_vnr(event->pid);
-	if (unlikely(event->mask & FAN_Q_OVERFLOW))
-		metadata->fd = FAN_NOFD;
-	else {
-		metadata->fd = create_fd(group, event, file);
-		if (metadata->fd < 0)
-			ret = metadata->fd;
-	}
-
-	return ret;
-}
-
 static struct fanotify_perm_event *dequeue_event(
 				struct fsnotify_group *group, int fd)
 {
@@ -205,37 +175,50 @@ static int process_access_response(struct fsnotify_group *group,
 }
 
 static ssize_t copy_event_to_user(struct fsnotify_group *group,
-				  struct fsnotify_event *event,
+				  struct fsnotify_event *fsn_event,
 				  char __user *buf, size_t count)
 {
-	struct fanotify_event_metadata fanotify_event_metadata;
+	struct fanotify_event_metadata metadata;
+	struct fanotify_event *event;
 	struct file *f;
 	int fd, ret;
 
-	pr_debug("%s: group=%p event=%p\n", __func__, group, event);
+	pr_debug("%s: group=%p event=%p\n", __func__, group, fsn_event);
 
-	ret = fill_event_metadata(group, &fanotify_event_metadata, event, &f);
-	if (ret < 0)
-		return ret;
+	event = container_of(fsn_event, struct fanotify_event, fse);
+	metadata.event_len = FAN_EVENT_METADATA_LEN;
+	metadata.metadata_len = FAN_EVENT_METADATA_LEN;
+	metadata.vers = FANOTIFY_METADATA_VERSION;
+	metadata.reserved = 0;
+	metadata.mask = event->mask & FANOTIFY_OUTGOING_EVENTS;
+	metadata.pid = pid_vnr(event->pid);
+
+	if (unlikely(event->mask & FAN_Q_OVERFLOW)) {
+		fd = FAN_NOFD;
+	} else {
+		fd = create_fd(group, event, &f);
+		if (fd < 0)
+			return fd;
+	}
+	metadata.fd = fd;
 
-	fd = fanotify_event_metadata.fd;
 	ret = -EFAULT;
 	/*
 	 * Sanity check copy size in case get_one_event() and
 	 * fill_event_metadata() event_len sizes ever get out of sync.
 	 */
-	if (WARN_ON_ONCE(fanotify_event_metadata.event_len > count))
+	if (WARN_ON_ONCE(metadata.event_len > count))
 		goto out_close_fd;
-	if (copy_to_user(buf, &fanotify_event_metadata,
-			 fanotify_event_metadata.event_len))
+
+	if (copy_to_user(buf, &metadata, metadata.event_len))
 		goto out_close_fd;
 
-	if (fanotify_is_perm_event(FANOTIFY_E(event)->mask))
-		FANOTIFY_PE(event)->fd = fd;
+	if (fanotify_is_perm_event(event->mask))
+		FANOTIFY_PE(fsn_event)->fd = fd;
 
 	if (fd != FAN_NOFD)
 		fd_install(fd, f);
-	return fanotify_event_metadata.event_len;
+	return metadata.event_len;
 
 out_close_fd:
 	if (fd != FAN_NOFD) {
-- 
2.17.1


^ permalink raw reply	[flat|nested] 34+ messages in thread

* [PATCH v5 07/17] fanotify: encode file identifier for FAN_REPORT_FID
  2019-01-10 17:04 [PATCH v5 00/17] fanotify: add support for more event types Amir Goldstein
                   ` (5 preceding siblings ...)
  2019-01-10 17:04 ` [PATCH v5 06/17] fanotify: open code fill_event_metadata() Amir Goldstein
@ 2019-01-10 17:04 ` Amir Goldstein
  2019-01-11  8:10   ` kbuild test robot
  2019-01-10 17:04 ` [PATCH v5 08/17] fanotify: copy event fid info to user Amir Goldstein
                   ` (10 subsequent siblings)
  17 siblings, 1 reply; 34+ messages in thread
From: Amir Goldstein @ 2019-01-10 17:04 UTC (permalink / raw)
  To: Jan Kara; +Cc: Matthew Bobrowski, linux-fsdevel

When user requests the flag FAN_REPORT_FID in fanotify_init(),
a unique file identifier of the event target object will be reported
with the event.

The file identifier includes the filesystem's fsid (i.e. from statfs(2))
and an NFS file handle of the file (i.e. from name_to_handle_at(2)).

The file identifier makes holding the path reference and passing a file
descriptor to user redundant, so those are disabled in a group with
FAN_REPORT_FID.

Encode fid and store it in event for a group with FAN_REPORT_FID.
Up to 12 bytes of file handle on 32bit arch (16 bytes on 64bit arch)
are stored inline in fanotify_event struct. Larger file handles are
stored in an external allocated buffer.

On failure to encode fid, we print a warning and queue the event
without the fid information.

Signed-off-by: Amir Goldstein <amir73il@gmail.com>
---
 fs/notify/fanotify/fanotify.c      | 81 +++++++++++++++++++++++++++---
 fs/notify/fanotify/fanotify.h      | 78 ++++++++++++++++++++++++++--
 fs/notify/fanotify/fanotify_user.c |  6 +--
 include/uapi/linux/fanotify.h      |  1 +
 4 files changed, 153 insertions(+), 13 deletions(-)

diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c
index d8e3b6e50844..e431f63c9f58 100644
--- a/fs/notify/fanotify/fanotify.c
+++ b/fs/notify/fanotify/fanotify.c
@@ -13,6 +13,7 @@
 #include <linux/wait.h>
 #include <linux/audit.h>
 #include <linux/sched/mm.h>
+#include <linux/statfs.h>
 
 #include "fanotify.h"
 
@@ -25,10 +26,18 @@ static bool should_merge(struct fsnotify_event *old_fsn,
 	old = FANOTIFY_E(old_fsn);
 	new = FANOTIFY_E(new_fsn);
 
-	if (old_fsn->inode == new_fsn->inode && old->pid == new->pid &&
-	    old->path.mnt == new->path.mnt &&
-	    old->path.dentry == new->path.dentry)
-		return true;
+	if (old_fsn->inode != new_fsn->inode || old->pid != new->pid ||
+	    old->fh_type != new->fh_type || old->fh_len != new->fh_len)
+		return false;
+
+	if (fanotify_event_has_path(old)) {
+		return old->path.mnt == new->path.mnt &&
+			old->path.dentry == new->path.dentry;
+	} else if (fanotify_event_has_fid(old)) {
+		return fanotify_fid_equal(&old->fid, &new->fid, old->fh_len);
+	}
+
+	/* Do not merge events if we failed to encode fid */
 	return false;
 }
 
@@ -143,6 +152,57 @@ static u32 fanotify_group_event_mask(struct fsnotify_iter_info *iter_info,
 		~marks_ignored_mask;
 }
 
+static int fanotify_encode_fid(struct fanotify_event *event,
+			       const struct path *path, gfp_t gfp)
+{
+	struct fanotify_fid *fid = &event->fid;
+	int dwords, bytes = 0;
+	struct kstatfs stat;
+	int err, type;
+
+	stat.f_fsid.val[0] = stat.f_fsid.val[1] = 0;
+	fid->ext_fh = NULL;
+	dwords = 0;
+	err = -ENOENT;
+	type = exportfs_encode_fh(path->dentry, NULL, &dwords,  0);
+	if (!dwords)
+		goto out_err;
+
+	err = vfs_statfs(path, &stat);
+	if (err)
+		goto out_err;
+
+	bytes = dwords << 2;
+	if (bytes > FANOTIFY_INLINE_FH_LEN) {
+		/* Treat failure to allocate fh as failure to allocate event */
+		err = -ENOMEM;
+		fid->ext_fh = kmalloc(bytes, gfp);
+		if (!fid->ext_fh)
+			goto out_err;
+	}
+
+	type = exportfs_encode_fh(path->dentry, fanotify_fid_fh(fid, bytes),
+				  &dwords,  0);
+	err = -EINVAL;
+	if (!type || type == FILEID_INVALID || bytes != dwords << 2)
+		goto out_err;
+
+	fid->fsid = stat.f_fsid;
+	event->fh_len = bytes;
+
+	return type;
+
+out_err:
+	pr_warn_ratelimited("fanotify: failed to encode fid (fsid=%x.%x, type=%d, bytes=%d, err=%i)\n",
+			    stat.f_fsid.val[0], stat.f_fsid.val[1],
+			    type, bytes, err);
+	kfree(fid->ext_fh);
+	fid->ext_fh = NULL;
+	event->fh_len = 0;
+
+	return FILEID_INVALID;
+}
+
 struct fanotify_event *fanotify_alloc_event(struct fsnotify_group *group,
 						 struct inode *inode, u32 mask,
 						 const struct path *path)
@@ -181,10 +241,16 @@ init: __maybe_unused
 		event->pid = get_pid(task_pid(current));
 	else
 		event->pid = get_pid(task_tgid(current));
-	if (path) {
+	event->fh_len = 0;
+	if (path && FAN_GROUP_FLAG(group, FAN_REPORT_FID)) {
+		/* Report the event without a file identifier on encode error */
+		event->fh_type = fanotify_encode_fid(event, path, gfp);
+	} else if (path) {
+		event->fh_type = FILEID_ROOT;
 		event->path = *path;
 		path_get(&event->path);
 	} else {
+		event->fh_type = FILEID_INVALID;
 		event->path.mnt = NULL;
 		event->path.dentry = NULL;
 	}
@@ -281,7 +347,10 @@ static void fanotify_free_event(struct fsnotify_event *fsn_event)
 	struct fanotify_event *event;
 
 	event = FANOTIFY_E(fsn_event);
-	path_put(&event->path);
+	if (fanotify_event_has_path(event))
+		path_put(&event->path);
+	else if (fanotify_event_has_ext_fh(event))
+		kfree(event->fid.ext_fh);
 	put_pid(event->pid);
 	if (fanotify_is_perm_event(event->mask)) {
 		kmem_cache_free(fanotify_perm_event_cachep,
diff --git a/fs/notify/fanotify/fanotify.h b/fs/notify/fanotify/fanotify.h
index 898b5b2bc1c7..271482fb9611 100644
--- a/fs/notify/fanotify/fanotify.h
+++ b/fs/notify/fanotify/fanotify.h
@@ -2,11 +2,49 @@
 #include <linux/fsnotify_backend.h>
 #include <linux/path.h>
 #include <linux/slab.h>
+#include <linux/exportfs.h>
 
 extern struct kmem_cache *fanotify_mark_cache;
 extern struct kmem_cache *fanotify_event_cachep;
 extern struct kmem_cache *fanotify_perm_event_cachep;
 
+/*
+ * 3 dwords are sufficient for most local fs (64bit ino, 32bit generation).
+ * For 32bit arch, fid increases the size of fanotify_event by 12 bytes and
+ * fh_* fields increase the size of fanotify_event by another 4 bytes.
+ * For 64bit arch, fid increases the size of fanotify_fid by 8 bytes and
+ * fh_* fields are packed in a hole after mask.
+ */
+#if BITS_PER_LONG == 32
+#define FANOTIFY_INLINE_FH_LEN	(3 << 2)
+#else
+#define FANOTIFY_INLINE_FH_LEN	(4 << 2)
+#endif
+
+struct fanotify_fid {
+	__kernel_fsid_t fsid;
+	union {
+		unsigned char fh[FANOTIFY_INLINE_FH_LEN];
+		unsigned char *ext_fh;
+	};
+};
+
+static inline void *fanotify_fid_fh(struct fanotify_fid *fid,
+				    unsigned int fh_len)
+{
+	return fh_len <= FANOTIFY_INLINE_FH_LEN ? fid->fh : fid->ext_fh;
+}
+
+static inline bool fanotify_fid_equal(struct fanotify_fid *fid1,
+				      struct fanotify_fid *fid2,
+				      unsigned int fh_len)
+{
+	return fid1->fsid.val[0] == fid2->fsid.val[0] &&
+		fid1->fsid.val[1] == fid2->fsid.val[1] &&
+		!memcmp(fanotify_fid_fh(fid1, fh_len),
+			fanotify_fid_fh(fid2, fh_len), fh_len);
+}
+
 /*
  * Structure for normal fanotify events. It gets allocated in
  * fanotify_handle_event() and freed when the information is retrieved by
@@ -16,13 +54,47 @@ struct fanotify_event {
 	struct fsnotify_event fse;
 	u32 mask;
 	/*
-	 * We hold ref to this path so it may be dereferenced at any point
-	 * during this object's lifetime
+	 * Those fields are outside fanotify_fid to pack fanotify_event nicely
+	 * on 64bit arch and to use fh_type as an indication of whether path
+	 * or fid are used in the union:
+	 * FILEID_ROOT (0) for path, > 0 for fid, FILEID_INVALID for neither.
 	 */
-	struct path path;
+	u8 fh_type;
+	u8 fh_len;
+	u16 pad;
+	union {
+		/*
+		 * We hold ref to this path so it may be dereferenced at any
+		 * point during this object's lifetime
+		 */
+		struct path path;
+		/*
+		 * With FAN_REPORT_FID, we do not hold any reference on the
+		 * victim object. Instead we store its NFS file handle and its
+		 * filesystem's fsid as a unique identifier.
+		 */
+		struct fanotify_fid fid;
+	};
 	struct pid *pid;
 };
 
+static inline bool fanotify_event_has_path(struct fanotify_event *event)
+{
+	return event->fh_type == FILEID_ROOT;
+}
+
+static inline bool fanotify_event_has_fid(struct fanotify_event *event)
+{
+	return event->fh_type != FILEID_ROOT &&
+		event->fh_type != FILEID_INVALID;
+}
+
+static inline bool fanotify_event_has_ext_fh(struct fanotify_event *event)
+{
+	return fanotify_event_has_fid(event) &&
+		event->fh_len > FANOTIFY_INLINE_FH_LEN;
+}
+
 /*
  * Structure for permission fanotify events. It gets allocated and freed in
  * fanotify_handle_event() since we wait there for user response. When the
diff --git a/fs/notify/fanotify/fanotify_user.c b/fs/notify/fanotify/fanotify_user.c
index 2f4901ac090c..68a1cb18ddd8 100644
--- a/fs/notify/fanotify/fanotify_user.c
+++ b/fs/notify/fanotify/fanotify_user.c
@@ -181,7 +181,7 @@ static ssize_t copy_event_to_user(struct fsnotify_group *group,
 	struct fanotify_event_metadata metadata;
 	struct fanotify_event *event;
 	struct file *f;
-	int fd, ret;
+	int ret, fd = FAN_NOFD;
 
 	pr_debug("%s: group=%p event=%p\n", __func__, group, fsn_event);
 
@@ -193,9 +193,7 @@ static ssize_t copy_event_to_user(struct fsnotify_group *group,
 	metadata.mask = event->mask & FANOTIFY_OUTGOING_EVENTS;
 	metadata.pid = pid_vnr(event->pid);
 
-	if (unlikely(event->mask & FAN_Q_OVERFLOW)) {
-		fd = FAN_NOFD;
-	} else {
+	if (fanotify_event_has_path(event)) {
 		fd = create_fd(group, event, &f);
 		if (fd < 0)
 			return fd;
diff --git a/include/uapi/linux/fanotify.h b/include/uapi/linux/fanotify.h
index 909c98fcace2..d07f3cbc2786 100644
--- a/include/uapi/linux/fanotify.h
+++ b/include/uapi/linux/fanotify.h
@@ -44,6 +44,7 @@
 
 /* Flags to determine fanotify event format */
 #define FAN_REPORT_TID		0x00000100	/* event->pid is thread id */
+#define FAN_REPORT_FID		0x00000200	/* Report unique file id */
 
 /* Deprecated - do not use this in programs and do not add new flags here! */
 #define FAN_ALL_INIT_FLAGS	(FAN_CLOEXEC | FAN_NONBLOCK | \
-- 
2.17.1


^ permalink raw reply	[flat|nested] 34+ messages in thread

* [PATCH v5 08/17] fanotify: copy event fid info to user
  2019-01-10 17:04 [PATCH v5 00/17] fanotify: add support for more event types Amir Goldstein
                   ` (6 preceding siblings ...)
  2019-01-10 17:04 ` [PATCH v5 07/17] fanotify: encode file identifier for FAN_REPORT_FID Amir Goldstein
@ 2019-01-10 17:04 ` Amir Goldstein
  2019-02-06 17:41   ` Jan Kara
  2019-01-10 17:04 ` [PATCH v5 09/17] fanotify: enable FAN_REPORT_FID init flag Amir Goldstein
                   ` (9 subsequent siblings)
  17 siblings, 1 reply; 34+ messages in thread
From: Amir Goldstein @ 2019-01-10 17:04 UTC (permalink / raw)
  To: Jan Kara; +Cc: Matthew Bobrowski, linux-fsdevel, linux-api

If group requested FAN_REPORT_FID and event has file identifier,
copy that information to user reading the event after event metadata.

fid information is formatted as struct fanotify_event_info_fid
that includes a generic header struct fanotify_event_info_header,
so that other info types could be defined in the future using the
same header.

metadata->event_len includes the length of the fid information.

The fid information includes the filesystem's fsid (see statfs(2))
followed by an NFS file handle of the file that could be passed as
an argument to open_by_handle_at(2).

Cc: <linux-api@vger.kernel.org>
Signed-off-by: Amir Goldstein <amir73il@gmail.com>
---
 fs/notify/fanotify/fanotify.h      |  5 ++
 fs/notify/fanotify/fanotify_user.c | 82 ++++++++++++++++++++++++++++--
 include/uapi/linux/fanotify.h      | 20 ++++++++
 3 files changed, 102 insertions(+), 5 deletions(-)

diff --git a/fs/notify/fanotify/fanotify.h b/fs/notify/fanotify/fanotify.h
index 271482fb9611..4aafc7144c3d 100644
--- a/fs/notify/fanotify/fanotify.h
+++ b/fs/notify/fanotify/fanotify.h
@@ -95,6 +95,11 @@ static inline bool fanotify_event_has_ext_fh(struct fanotify_event *event)
 		event->fh_len > FANOTIFY_INLINE_FH_LEN;
 }
 
+static inline void *fanotify_event_fh(struct fanotify_event *event)
+{
+	return fanotify_fid_fh(&event->fid, event->fh_len);
+}
+
 /*
  * Structure for permission fanotify events. It gets allocated and freed in
  * fanotify_handle_event() since we wait there for user response. When the
diff --git a/fs/notify/fanotify/fanotify_user.c b/fs/notify/fanotify/fanotify_user.c
index 68a1cb18ddd8..bd42e681a052 100644
--- a/fs/notify/fanotify/fanotify_user.c
+++ b/fs/notify/fanotify/fanotify_user.c
@@ -47,6 +47,18 @@ struct kmem_cache *fanotify_mark_cache __read_mostly;
 struct kmem_cache *fanotify_event_cachep __read_mostly;
 struct kmem_cache *fanotify_perm_event_cachep __read_mostly;
 
+#define FANOTIFY_EVENT_ALIGN (sizeof(struct fanotify_event_info_header))
+
+static int fanotify_event_info_len(struct fanotify_event *event)
+{
+	if (!fanotify_event_has_fid(event))
+		return 0;
+
+	return roundup(sizeof(struct fanotify_event_info_fid) +
+		       sizeof(struct file_handle) + event->fh_len,
+		       FANOTIFY_EVENT_ALIGN);
+}
+
 /*
  * Get an fsnotify notification event if one exists and is small
  * enough to fit in "count". Return an error pointer if the count
@@ -57,6 +69,9 @@ struct kmem_cache *fanotify_perm_event_cachep __read_mostly;
 static struct fsnotify_event *get_one_event(struct fsnotify_group *group,
 					    size_t count)
 {
+	size_t event_size = FAN_EVENT_METADATA_LEN;
+	struct fanotify_event *event;
+
 	assert_spin_locked(&group->notification_lock);
 
 	pr_debug("%s: group=%p count=%zd\n", __func__, group, count);
@@ -64,11 +79,18 @@ static struct fsnotify_event *get_one_event(struct fsnotify_group *group,
 	if (fsnotify_notify_queue_is_empty(group))
 		return NULL;
 
-	if (FAN_EVENT_METADATA_LEN > count)
+	if (FAN_GROUP_FLAG(group, FAN_REPORT_FID)) {
+		event = FANOTIFY_E(fsnotify_peek_first_event(group));
+		event_size += fanotify_event_info_len(event);
+	}
+
+	if (event_size > count)
 		return ERR_PTR(-EINVAL);
 
-	/* held the notification_lock the whole time, so this is the
-	 * same event we peeked above */
+	/*
+	 * Held the notification_lock the whole time, so this is the
+	 * same event we peeked above
+	 */
 	return fsnotify_remove_first_event(group);
 }
 
@@ -174,6 +196,48 @@ static int process_access_response(struct fsnotify_group *group,
 	return 0;
 }
 
+static int copy_fid_to_user(struct fanotify_event *event, char __user *buf)
+{
+	struct fanotify_event_info_fid info = { };
+	struct file_handle handle = { };
+	size_t fh_len = event->fh_len;
+	size_t len = fanotify_event_info_len(event);
+
+	if (!len)
+		return 0;
+
+	if (WARN_ON_ONCE(len < sizeof(info) + sizeof(handle) + fh_len))
+		return -EFAULT;
+
+	/* Copy event info fid header followed by vaiable sized file handle */
+	info.hdr.info_type = FAN_EVENT_INFO_TYPE_FID;
+	info.hdr.len = len;
+	info.fsid = event->fid.fsid;
+	if (copy_to_user(buf, &info, sizeof(info)))
+		return -EFAULT;
+
+	buf += sizeof(info);
+	len -= sizeof(info);
+	handle.handle_type = event->fh_type;
+	handle.handle_bytes = fh_len;
+	if (copy_to_user(buf, &handle, sizeof(handle)))
+		return -EFAULT;
+
+	buf += sizeof(handle);
+	len -= sizeof(handle);
+	if (copy_to_user(buf, fanotify_event_fh(event), fh_len))
+		return -EFAULT;
+
+	/* Pad with 0's */
+	buf += fh_len;
+	len -= fh_len;
+	WARN_ON_ONCE(len < 0 || len >= FANOTIFY_EVENT_ALIGN);
+	if (len > 0 && clear_user(buf, len))
+		return -EFAULT;
+
+	return 0;
+}
+
 static ssize_t copy_event_to_user(struct fsnotify_group *group,
 				  struct fsnotify_event *fsn_event,
 				  char __user *buf, size_t count)
@@ -197,6 +261,8 @@ static ssize_t copy_event_to_user(struct fsnotify_group *group,
 		fd = create_fd(group, event, &f);
 		if (fd < 0)
 			return fd;
+	} else if (fanotify_event_has_fid(event)) {
+		metadata.event_len += fanotify_event_info_len(event);
 	}
 	metadata.fd = fd;
 
@@ -208,14 +274,20 @@ static ssize_t copy_event_to_user(struct fsnotify_group *group,
 	if (WARN_ON_ONCE(metadata.event_len > count))
 		goto out_close_fd;
 
-	if (copy_to_user(buf, &metadata, metadata.event_len))
+	if (copy_to_user(buf, &metadata, FAN_EVENT_METADATA_LEN))
 		goto out_close_fd;
 
 	if (fanotify_is_perm_event(event->mask))
 		FANOTIFY_PE(fsn_event)->fd = fd;
 
-	if (fd != FAN_NOFD)
+	if (fanotify_event_has_path(event)) {
 		fd_install(fd, f);
+	} else if (fanotify_event_has_fid(event)) {
+		ret = copy_fid_to_user(event, buf + FAN_EVENT_METADATA_LEN);
+		if (ret < 0)
+			return ret;
+	}
+
 	return metadata.event_len;
 
 out_close_fd:
diff --git a/include/uapi/linux/fanotify.h b/include/uapi/linux/fanotify.h
index d07f3cbc2786..959ae2bdc7ca 100644
--- a/include/uapi/linux/fanotify.h
+++ b/include/uapi/linux/fanotify.h
@@ -107,6 +107,26 @@ struct fanotify_event_metadata {
 	__s32 pid;
 };
 
+#define FAN_EVENT_INFO_TYPE_FID		1
+
+/* Variable length info record following event metadata */
+struct fanotify_event_info_header {
+	__u8 info_type;
+	__u8 pad;
+	__u16 len;
+};
+
+/* Unique file identifier info record */
+struct fanotify_event_info_fid {
+	struct fanotify_event_info_header hdr;
+	__kernel_fsid_t fsid;
+	/*
+	 * Following is an opaque struct file_handle that can be passed as
+	 * an argument to open_by_handle_at(2).
+	 */
+	unsigned char handle[0];
+};
+
 struct fanotify_response {
 	__s32 fd;
 	__u32 response;
-- 
2.17.1


^ permalink raw reply	[flat|nested] 34+ messages in thread

* [PATCH v5 09/17] fanotify: enable FAN_REPORT_FID init flag
  2019-01-10 17:04 [PATCH v5 00/17] fanotify: add support for more event types Amir Goldstein
                   ` (7 preceding siblings ...)
  2019-01-10 17:04 ` [PATCH v5 08/17] fanotify: copy event fid info to user Amir Goldstein
@ 2019-01-10 17:04 ` Amir Goldstein
  2019-01-10 17:04 ` [PATCH v5 10/17] fanotify: cache fsid in fsnotify_mark_connector Amir Goldstein
                   ` (8 subsequent siblings)
  17 siblings, 0 replies; 34+ messages in thread
From: Amir Goldstein @ 2019-01-10 17:04 UTC (permalink / raw)
  To: Jan Kara; +Cc: Matthew Bobrowski, linux-fsdevel, linux-api

When setting up an fanotify listener, user may request to get fid
information in event instead of an open file descriptor.

The fid obtained with event on a watched object contains the file
handle returned by name_to_handle_at(2) and fsid returned by statfs(2).

Restrict FAN_REPORT_FID to class FAN_CLASS_NOTIF, because we have have
no good reason to support reporting fid on permission events.

When setting a mark, we need to make sure that the filesystem
supports encoding file handles with name_to_handle_at(2) and that
statfs(2) encodes a non-zero fsid.

Cc: <linux-api@vger.kernel.org>
Signed-off-by: Amir Goldstein <amir73il@gmail.com>
---
 fs/notify/fanotify/fanotify_user.c | 61 +++++++++++++++++++++++++++++-
 include/linux/fanotify.h           |  2 +-
 2 files changed, 61 insertions(+), 2 deletions(-)

diff --git a/fs/notify/fanotify/fanotify_user.c b/fs/notify/fanotify/fanotify_user.c
index bd42e681a052..211ec6332d31 100644
--- a/fs/notify/fanotify/fanotify_user.c
+++ b/fs/notify/fanotify/fanotify_user.c
@@ -17,6 +17,8 @@
 #include <linux/compat.h>
 #include <linux/sched/signal.h>
 #include <linux/memcontrol.h>
+#include <linux/statfs.h>
+#include <linux/exportfs.h>
 
 #include <asm/ioctls.h>
 
@@ -768,6 +770,10 @@ SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags)
 		return -EINVAL;
 	}
 
+	if ((flags & FAN_REPORT_FID) &&
+	    (flags & FANOTIFY_CLASS_BITS) != FAN_CLASS_NOTIF)
+		return -EINVAL;
+
 	user = get_current_user();
 	if (atomic_read(&user->fanotify_listeners) > FANOTIFY_DEFAULT_MAX_LISTENERS) {
 		free_uid(user);
@@ -854,6 +860,52 @@ SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags)
 	return fd;
 }
 
+/* Check if filesystem can encode a unique fid */
+static int fanotify_test_fid(struct path *path)
+{
+	struct kstatfs stat, root_stat;
+	struct path root = {
+		.mnt = path->mnt,
+		.dentry = path->dentry->d_sb->s_root,
+	};
+	int err;
+
+	/*
+	 * Make sure path is not in filesystem with zero fsid (e.g. tmpfs).
+	 */
+	err = vfs_statfs(path, &stat);
+	if (err)
+		return err;
+
+	if (!stat.f_fsid.val[0] && !stat.f_fsid.val[1])
+		return -ENODEV;
+
+	/*
+	 * Make sure path is not inside a filesystem subvolume (e.g. btrfs)
+	 * which uses a different fsid than sb root.
+	 */
+	err = vfs_statfs(&root, &root_stat);
+	if (err)
+		return err;
+
+	if (root_stat.f_fsid.val[0] != stat.f_fsid.val[0] ||
+	    root_stat.f_fsid.val[1] != stat.f_fsid.val[1])
+		return -EXDEV;
+
+	/*
+	 * We need to make sure that the file system supports at least
+	 * encoding a file handle so user can use name_to_handle_at() to
+	 * compare fid returned with event to the file handle of watched
+	 * objects. However, name_to_handle_at() requires that the
+	 * filesystem also supports decoding file handles.
+	 */
+	if (!path->dentry->d_sb->s_export_op ||
+	    !path->dentry->d_sb->s_export_op->fh_to_dentry)
+		return -EOPNOTSUPP;
+
+	return 0;
+}
+
 static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask,
 			    int dfd, const char  __user *pathname)
 {
@@ -939,6 +991,12 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask,
 	if (ret)
 		goto fput_and_out;
 
+	if (FAN_GROUP_FLAG(group, FAN_REPORT_FID)) {
+		ret = fanotify_test_fid(&path);
+		if (ret)
+			goto path_put_and_out;
+	}
+
 	/* inode held in place by reference to path; group by fget on fd */
 	if (mark_type == FAN_MARK_INODE)
 		inode = path.dentry->d_inode;
@@ -967,6 +1025,7 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask,
 		ret = -EINVAL;
 	}
 
+path_put_and_out:
 	path_put(&path);
 fput_and_out:
 	fdput(f);
@@ -1003,7 +1062,7 @@ COMPAT_SYSCALL_DEFINE6(fanotify_mark,
  */
 static int __init fanotify_user_setup(void)
 {
-	BUILD_BUG_ON(HWEIGHT32(FANOTIFY_INIT_FLAGS) != 7);
+	BUILD_BUG_ON(HWEIGHT32(FANOTIFY_INIT_FLAGS) != 8);
 	BUILD_BUG_ON(HWEIGHT32(FANOTIFY_MARK_FLAGS) != 9);
 
 	fanotify_mark_cache = KMEM_CACHE(fsnotify_mark,
diff --git a/include/linux/fanotify.h b/include/linux/fanotify.h
index 9e2142795335..f59be967f72b 100644
--- a/include/linux/fanotify.h
+++ b/include/linux/fanotify.h
@@ -19,7 +19,7 @@
 				 FAN_CLASS_PRE_CONTENT)
 
 #define FANOTIFY_INIT_FLAGS	(FANOTIFY_CLASS_BITS | \
-				 FAN_REPORT_TID | \
+				 FAN_REPORT_TID | FAN_REPORT_FID | \
 				 FAN_CLOEXEC | FAN_NONBLOCK | \
 				 FAN_UNLIMITED_QUEUE | FAN_UNLIMITED_MARKS)
 
-- 
2.17.1


^ permalink raw reply	[flat|nested] 34+ messages in thread

* [PATCH v5 10/17] fanotify: cache fsid in fsnotify_mark_connector
  2019-01-10 17:04 [PATCH v5 00/17] fanotify: add support for more event types Amir Goldstein
                   ` (8 preceding siblings ...)
  2019-01-10 17:04 ` [PATCH v5 09/17] fanotify: enable FAN_REPORT_FID init flag Amir Goldstein
@ 2019-01-10 17:04 ` Amir Goldstein
  2019-01-11  3:13   ` kbuild test robot
                     ` (2 more replies)
  2019-01-10 17:04 ` [PATCH v5 11/17] vfs: add vfs_get_fsid() helper Amir Goldstein
                   ` (7 subsequent siblings)
  17 siblings, 3 replies; 34+ messages in thread
From: Amir Goldstein @ 2019-01-10 17:04 UTC (permalink / raw)
  To: Jan Kara; +Cc: Matthew Bobrowski, linux-fsdevel

For FAN_REPORT_FID, we need to encode fid with fsid of the filesystem on
every event. To avoid having to call vfs_statfs() on every event to get
fsid, we store the fsid in fsnotify_mark_connector on the first time we
add a mark and on handle event we use the cached fsid.

Subsequent calls to add mark on the same object are expected to pass the
same fsid, so the call will fail on cached fsid mismatch.

If an event is reported on several mark types (inode, mount, filesystem),
all connectors should already have the same fsid, so we use the cached
fsid from the first connector.

Suggested-by: Jan Kara <jack@suse.cz>
Signed-off-by: Amir Goldstein <amir73il@gmail.com>
---
 fs/notify/fanotify/fanotify.c      | 51 +++++++++++++++++-------
 fs/notify/fanotify/fanotify.h      |  5 ++-
 fs/notify/fanotify/fanotify_user.c | 62 ++++++++++++++++++------------
 fs/notify/mark.c                   | 47 +++++++++++++++++-----
 include/linux/fsnotify_backend.h   | 24 +++++++++---
 5 files changed, 135 insertions(+), 54 deletions(-)

diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c
index e431f63c9f58..1bbf8b90dd83 100644
--- a/fs/notify/fanotify/fanotify.c
+++ b/fs/notify/fanotify/fanotify.c
@@ -153,14 +153,16 @@ static u32 fanotify_group_event_mask(struct fsnotify_iter_info *iter_info,
 }
 
 static int fanotify_encode_fid(struct fanotify_event *event,
-			       const struct path *path, gfp_t gfp)
+			       const struct path *path, gfp_t gfp,
+			       __kernel_fsid_t *fsid)
 {
 	struct fanotify_fid *fid = &event->fid;
 	int dwords, bytes = 0;
-	struct kstatfs stat;
 	int err, type;
 
-	stat.f_fsid.val[0] = stat.f_fsid.val[1] = 0;
+	if (!fsid)
+		goto out_err;
+
 	fid->ext_fh = NULL;
 	dwords = 0;
 	err = -ENOENT;
@@ -168,10 +170,6 @@ static int fanotify_encode_fid(struct fanotify_event *event,
 	if (!dwords)
 		goto out_err;
 
-	err = vfs_statfs(path, &stat);
-	if (err)
-		goto out_err;
-
 	bytes = dwords << 2;
 	if (bytes > FANOTIFY_INLINE_FH_LEN) {
 		/* Treat failure to allocate fh as failure to allocate event */
@@ -187,14 +185,14 @@ static int fanotify_encode_fid(struct fanotify_event *event,
 	if (!type || type == FILEID_INVALID || bytes != dwords << 2)
 		goto out_err;
 
-	fid->fsid = stat.f_fsid;
+	fid->fsid = *fsid;
 	event->fh_len = bytes;
 
 	return type;
 
 out_err:
 	pr_warn_ratelimited("fanotify: failed to encode fid (fsid=%x.%x, type=%d, bytes=%d, err=%i)\n",
-			    stat.f_fsid.val[0], stat.f_fsid.val[1],
+			    fsid ? fsid->val[0] : 0, fsid ? fsid->val[1] : 0,
 			    type, bytes, err);
 	kfree(fid->ext_fh);
 	fid->ext_fh = NULL;
@@ -204,8 +202,9 @@ static int fanotify_encode_fid(struct fanotify_event *event,
 }
 
 struct fanotify_event *fanotify_alloc_event(struct fsnotify_group *group,
-						 struct inode *inode, u32 mask,
-						 const struct path *path)
+					    struct inode *inode, u32 mask,
+					    const struct path *path,
+					    __kernel_fsid_t *fsid)
 {
 	struct fanotify_event *event = NULL;
 	gfp_t gfp = GFP_KERNEL_ACCOUNT;
@@ -244,7 +243,7 @@ init: __maybe_unused
 	event->fh_len = 0;
 	if (path && FAN_GROUP_FLAG(group, FAN_REPORT_FID)) {
 		/* Report the event without a file identifier on encode error */
-		event->fh_type = fanotify_encode_fid(event, path, gfp);
+		event->fh_type = fanotify_encode_fid(event, path, gfp, fsid);
 	} else if (path) {
 		event->fh_type = FILEID_ROOT;
 		event->path = *path;
@@ -259,6 +258,28 @@ init: __maybe_unused
 	return event;
 }
 
+/*
+ * Get cached fsid of the filesystem containing the object from any connector.
+ * All connectors are supposed to have the same fsid, but we do not verify that
+ * here.
+ */
+static __kernel_fsid_t *fanotify_get_fsid(struct fsnotify_iter_info *iter_info,
+					  __kernel_fsid_t *fsid)
+{
+	int type;
+
+	fsnotify_foreach_obj_type(type) {
+		if (!fsnotify_iter_should_report_type(iter_info, type))
+			continue;
+
+		*fsid = iter_info->marks[type]->connector->fsid;
+		if (!WARN_ON_ONCE(!fsid->val[0] && !fsid->val[1]))
+			return fsid;
+	}
+
+	return NULL;
+}
+
 static int fanotify_handle_event(struct fsnotify_group *group,
 				 struct inode *inode,
 				 u32 mask, const void *data, int data_type,
@@ -268,6 +289,7 @@ static int fanotify_handle_event(struct fsnotify_group *group,
 	int ret = 0;
 	struct fanotify_event *event;
 	struct fsnotify_event *fsn_event;
+	__kernel_fsid_t __fsid, *fsid = NULL;
 
 	BUILD_BUG_ON(FAN_ACCESS != FS_ACCESS);
 	BUILD_BUG_ON(FAN_MODIFY != FS_MODIFY);
@@ -300,7 +322,10 @@ static int fanotify_handle_event(struct fsnotify_group *group,
 			return 0;
 	}
 
-	event = fanotify_alloc_event(group, inode, mask, data);
+	if (FAN_GROUP_FLAG(group, FAN_REPORT_FID))
+		fsid = fanotify_get_fsid(iter_info, &__fsid);
+
+	event = fanotify_alloc_event(group, inode, mask, data, fsid);
 	ret = -ENOMEM;
 	if (unlikely(!event)) {
 		/*
diff --git a/fs/notify/fanotify/fanotify.h b/fs/notify/fanotify/fanotify.h
index 4aafc7144c3d..5b072afa4e19 100644
--- a/fs/notify/fanotify/fanotify.h
+++ b/fs/notify/fanotify/fanotify.h
@@ -131,5 +131,6 @@ static inline struct fanotify_event *FANOTIFY_E(struct fsnotify_event *fse)
 }
 
 struct fanotify_event *fanotify_alloc_event(struct fsnotify_group *group,
-						 struct inode *inode, u32 mask,
-						 const struct path *path);
+					    struct inode *inode, u32 mask,
+					    const struct path *path,
+					    __kernel_fsid_t *fsid);
diff --git a/fs/notify/fanotify/fanotify_user.c b/fs/notify/fanotify/fanotify_user.c
index 211ec6332d31..467e6431fbe9 100644
--- a/fs/notify/fanotify/fanotify_user.c
+++ b/fs/notify/fanotify/fanotify_user.c
@@ -653,7 +653,8 @@ static __u32 fanotify_mark_add_to_mask(struct fsnotify_mark *fsn_mark,
 
 static struct fsnotify_mark *fanotify_add_new_mark(struct fsnotify_group *group,
 						   fsnotify_connp_t *connp,
-						   unsigned int type)
+						   unsigned int type,
+						   __kernel_fsid_t *fsid)
 {
 	struct fsnotify_mark *mark;
 	int ret;
@@ -666,7 +667,7 @@ static struct fsnotify_mark *fanotify_add_new_mark(struct fsnotify_group *group,
 		return ERR_PTR(-ENOMEM);
 
 	fsnotify_init_mark(mark, group);
-	ret = fsnotify_add_mark_locked(mark, connp, type, 0);
+	ret = fsnotify_add_mark_locked_fsid(mark, connp, type, 0, fsid);
 	if (ret) {
 		fsnotify_put_mark(mark);
 		return ERR_PTR(ret);
@@ -678,7 +679,8 @@ static struct fsnotify_mark *fanotify_add_new_mark(struct fsnotify_group *group,
 
 static int fanotify_add_mark(struct fsnotify_group *group,
 			     fsnotify_connp_t *connp, unsigned int type,
-			     __u32 mask, unsigned int flags)
+			     __u32 mask, unsigned int flags,
+			     __kernel_fsid_t *fsid)
 {
 	struct fsnotify_mark *fsn_mark;
 	__u32 added;
@@ -686,7 +688,7 @@ static int fanotify_add_mark(struct fsnotify_group *group,
 	mutex_lock(&group->mark_mutex);
 	fsn_mark = fsnotify_find_mark(connp, group);
 	if (!fsn_mark) {
-		fsn_mark = fanotify_add_new_mark(group, connp, type);
+		fsn_mark = fanotify_add_new_mark(group, connp, type, fsid);
 		if (IS_ERR(fsn_mark)) {
 			mutex_unlock(&group->mark_mutex);
 			return PTR_ERR(fsn_mark);
@@ -703,23 +705,23 @@ static int fanotify_add_mark(struct fsnotify_group *group,
 
 static int fanotify_add_vfsmount_mark(struct fsnotify_group *group,
 				      struct vfsmount *mnt, __u32 mask,
-				      unsigned int flags)
+				      unsigned int flags, __kernel_fsid_t *fsid)
 {
 	return fanotify_add_mark(group, &real_mount(mnt)->mnt_fsnotify_marks,
-				 FSNOTIFY_OBJ_TYPE_VFSMOUNT, mask, flags);
+				 FSNOTIFY_OBJ_TYPE_VFSMOUNT, mask, flags, fsid);
 }
 
 static int fanotify_add_sb_mark(struct fsnotify_group *group,
-				      struct super_block *sb, __u32 mask,
-				      unsigned int flags)
+				struct super_block *sb, __u32 mask,
+				unsigned int flags, __kernel_fsid_t *fsid)
 {
 	return fanotify_add_mark(group, &sb->s_fsnotify_marks,
-				 FSNOTIFY_OBJ_TYPE_SB, mask, flags);
+				 FSNOTIFY_OBJ_TYPE_SB, mask, flags, fsid);
 }
 
 static int fanotify_add_inode_mark(struct fsnotify_group *group,
 				   struct inode *inode, __u32 mask,
-				   unsigned int flags)
+				   unsigned int flags, __kernel_fsid_t *fsid)
 {
 	pr_debug("%s: group=%p inode=%p\n", __func__, group, inode);
 
@@ -734,7 +736,7 @@ static int fanotify_add_inode_mark(struct fsnotify_group *group,
 		return 0;
 
 	return fanotify_add_mark(group, &inode->i_fsnotify_marks,
-				 FSNOTIFY_OBJ_TYPE_INODE, mask, flags);
+				 FSNOTIFY_OBJ_TYPE_INODE, mask, flags, fsid);
 }
 
 /* fanotify syscalls */
@@ -798,7 +800,7 @@ SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags)
 	atomic_inc(&user->fanotify_listeners);
 	group->memcg = get_mem_cgroup_from_mm(current->mm);
 
-	oevent = fanotify_alloc_event(group, NULL, FS_Q_OVERFLOW, NULL);
+	oevent = fanotify_alloc_event(group, NULL, FS_Q_OVERFLOW, NULL, NULL);
 	if (unlikely(!oevent)) {
 		fd = -ENOMEM;
 		goto out_destroy_group;
@@ -861,9 +863,9 @@ SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags)
 }
 
 /* Check if filesystem can encode a unique fid */
-static int fanotify_test_fid(struct path *path)
+static int fanotify_test_fid(struct path *path, struct kstatfs *stat)
 {
-	struct kstatfs stat, root_stat;
+	struct kstatfs root_stat;
 	struct path root = {
 		.mnt = path->mnt,
 		.dentry = path->dentry->d_sb->s_root,
@@ -873,11 +875,11 @@ static int fanotify_test_fid(struct path *path)
 	/*
 	 * Make sure path is not in filesystem with zero fsid (e.g. tmpfs).
 	 */
-	err = vfs_statfs(path, &stat);
+	err = vfs_statfs(path, stat);
 	if (err)
 		return err;
 
-	if (!stat.f_fsid.val[0] && !stat.f_fsid.val[1])
+	if (!stat->f_fsid.val[0] && !stat->f_fsid.val[1])
 		return -ENODEV;
 
 	/*
@@ -888,8 +890,8 @@ static int fanotify_test_fid(struct path *path)
 	if (err)
 		return err;
 
-	if (root_stat.f_fsid.val[0] != stat.f_fsid.val[0] ||
-	    root_stat.f_fsid.val[1] != stat.f_fsid.val[1])
+	if (root_stat.f_fsid.val[0] != stat->f_fsid.val[0] ||
+	    root_stat.f_fsid.val[1] != stat->f_fsid.val[1])
 		return -EXDEV;
 
 	/*
@@ -914,6 +916,8 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask,
 	struct fsnotify_group *group;
 	struct fd f;
 	struct path path;
+	struct kstatfs stat;
+	__kernel_fsid_t *fsid = NULL;
 	u32 valid_mask = FANOTIFY_EVENTS | FANOTIFY_EVENT_FLAGS;
 	unsigned int mark_type = flags & FANOTIFY_MARK_TYPE_BITS;
 	int ret;
@@ -992,9 +996,11 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask,
 		goto fput_and_out;
 
 	if (FAN_GROUP_FLAG(group, FAN_REPORT_FID)) {
-		ret = fanotify_test_fid(&path);
+		ret = fanotify_test_fid(&path, &stat);
 		if (ret)
 			goto path_put_and_out;
+
+		fsid = &stat.f_fsid;
 	}
 
 	/* inode held in place by reference to path; group by fget on fd */
@@ -1007,19 +1013,25 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask,
 	switch (flags & (FAN_MARK_ADD | FAN_MARK_REMOVE)) {
 	case FAN_MARK_ADD:
 		if (mark_type == FAN_MARK_MOUNT)
-			ret = fanotify_add_vfsmount_mark(group, mnt, mask, flags);
+			ret = fanotify_add_vfsmount_mark(group, mnt, mask,
+							 flags, fsid);
 		else if (mark_type == FAN_MARK_FILESYSTEM)
-			ret = fanotify_add_sb_mark(group, mnt->mnt_sb, mask, flags);
+			ret = fanotify_add_sb_mark(group, mnt->mnt_sb, mask,
+						   flags, fsid);
 		else
-			ret = fanotify_add_inode_mark(group, inode, mask, flags);
+			ret = fanotify_add_inode_mark(group, inode, mask,
+						      flags, fsid);
 		break;
 	case FAN_MARK_REMOVE:
 		if (mark_type == FAN_MARK_MOUNT)
-			ret = fanotify_remove_vfsmount_mark(group, mnt, mask, flags);
+			ret = fanotify_remove_vfsmount_mark(group, mnt, mask,
+							    flags);
 		else if (mark_type == FAN_MARK_FILESYSTEM)
-			ret = fanotify_remove_sb_mark(group, mnt->mnt_sb, mask, flags);
+			ret = fanotify_remove_sb_mark(group, mnt->mnt_sb, mask,
+						      flags);
 		else
-			ret = fanotify_remove_inode_mark(group, inode, mask, flags);
+			ret = fanotify_remove_inode_mark(group, inode, mask,
+							 flags);
 		break;
 	default:
 		ret = -EINVAL;
diff --git a/fs/notify/mark.c b/fs/notify/mark.c
index d2dd16cb5989..3c5f39cc7fa3 100644
--- a/fs/notify/mark.c
+++ b/fs/notify/mark.c
@@ -82,6 +82,7 @@
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/srcu.h>
+#include <linux/ratelimit.h>
 
 #include <linux/atomic.h>
 
@@ -481,7 +482,8 @@ int fsnotify_compare_groups(struct fsnotify_group *a, struct fsnotify_group *b)
 }
 
 static int fsnotify_attach_connector_to_object(fsnotify_connp_t *connp,
-					       unsigned int type)
+					       unsigned int type,
+					       __kernel_fsid_t *fsid)
 {
 	struct inode *inode = NULL;
 	struct fsnotify_mark_connector *conn;
@@ -493,6 +495,11 @@ static int fsnotify_attach_connector_to_object(fsnotify_connp_t *connp,
 	INIT_HLIST_HEAD(&conn->list);
 	conn->type = type;
 	conn->obj = connp;
+	/* Cache fsid of filesystem containing the object */
+	if (fsid)
+		conn->fsid = *fsid;
+	else
+		conn->fsid.val[0] = conn->fsid.val[1] = 0;
 	if (conn->type == FSNOTIFY_OBJ_TYPE_INODE)
 		inode = igrab(fsnotify_conn_inode(conn));
 	/*
@@ -544,7 +551,7 @@ static struct fsnotify_mark_connector *fsnotify_grab_connector(
  */
 static int fsnotify_add_mark_list(struct fsnotify_mark *mark,
 				  fsnotify_connp_t *connp, unsigned int type,
-				  int allow_dups)
+				  int allow_dups, __kernel_fsid_t *fsid)
 {
 	struct fsnotify_mark *lmark, *last = NULL;
 	struct fsnotify_mark_connector *conn;
@@ -553,15 +560,36 @@ static int fsnotify_add_mark_list(struct fsnotify_mark *mark,
 
 	if (WARN_ON(!fsnotify_valid_obj_type(type)))
 		return -EINVAL;
+
+	/* Backend is expected to check for zero fsid (e.g. tmpfs) */
+	if (fsid && WARN_ON_ONCE(!fsid->val[0] && !fsid->val[1]))
+		return -ENODEV;
+
 restart:
 	spin_lock(&mark->lock);
 	conn = fsnotify_grab_connector(connp);
 	if (!conn) {
 		spin_unlock(&mark->lock);
-		err = fsnotify_attach_connector_to_object(connp, type);
+		err = fsnotify_attach_connector_to_object(connp, type, fsid);
 		if (err)
 			return err;
 		goto restart;
+	} else if (fsid && (conn->fsid.val[0] || conn->fsid.val[1]) &&
+		   (fsid->val[0] != conn->fsid.val[0] ||
+		    fsid->val[1] != conn->fsid.val[1])) {
+		/*
+		 * Backend is expected to check for non uniform fsid
+		 * (e.g. btrfs), but maybe we missed something?
+		 * Only allow setting conn->fsid once to non zero fsid.
+		 * inotify and non-fid fanotify groups do not set nor test
+		 * conn->fsid.
+		 */
+		pr_warn_ratelimited("%s: fsid mismatch on object of type %u: %x.%x != %x.%x\n",
+				    __func__, conn->type,
+				    fsid->val[0], fsid->val[1],
+				    conn->fsid.val[0], conn->fsid.val[1]);
+		err = -EXDEV;
+		goto out_err;
 	}
 
 	/* is mark the first mark? */
@@ -604,9 +632,9 @@ static int fsnotify_add_mark_list(struct fsnotify_mark *mark,
  * These marks may be used for the fsnotify backend to determine which
  * event types should be delivered to which group.
  */
-int fsnotify_add_mark_locked(struct fsnotify_mark *mark,
-			     fsnotify_connp_t *connp, unsigned int type,
-			     int allow_dups)
+int fsnotify_add_mark_locked_fsid(struct fsnotify_mark *mark,
+				  fsnotify_connp_t *connp, unsigned int type,
+				  int allow_dups, __kernel_fsid_t *fsid)
 {
 	struct fsnotify_group *group = mark->group;
 	int ret = 0;
@@ -627,7 +655,7 @@ int fsnotify_add_mark_locked(struct fsnotify_mark *mark,
 	fsnotify_get_mark(mark); /* for g_list */
 	spin_unlock(&mark->lock);
 
-	ret = fsnotify_add_mark_list(mark, connp, type, allow_dups);
+	ret = fsnotify_add_mark_list(mark, connp, type, allow_dups, fsid);
 	if (ret)
 		goto err;
 
@@ -648,13 +676,14 @@ int fsnotify_add_mark_locked(struct fsnotify_mark *mark,
 }
 
 int fsnotify_add_mark(struct fsnotify_mark *mark, fsnotify_connp_t *connp,
-		      unsigned int type, int allow_dups)
+		      unsigned int type, int allow_dups, __kernel_fsid_t *fsid)
 {
 	int ret;
 	struct fsnotify_group *group = mark->group;
 
 	mutex_lock(&group->mark_mutex);
-	ret = fsnotify_add_mark_locked(mark, connp, type, allow_dups);
+	ret = fsnotify_add_mark_locked_fsid(mark, connp, type, allow_dups,
+					    fsid);
 	mutex_unlock(&group->mark_mutex);
 	return ret;
 }
diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h
index 1e4b88bd1443..b66c4199d629 100644
--- a/include/linux/fsnotify_backend.h
+++ b/include/linux/fsnotify_backend.h
@@ -293,6 +293,7 @@ typedef struct fsnotify_mark_connector __rcu *fsnotify_connp_t;
 struct fsnotify_mark_connector {
 	spinlock_t lock;
 	unsigned int type;	/* Type of object [lock] */
+	__kernel_fsid_t fsid;	/* fsid of filesystem containing object */
 	union {
 		/* Object pointer [lock] */
 		fsnotify_connp_t *obj;
@@ -433,20 +434,32 @@ extern void fsnotify_init_mark(struct fsnotify_mark *mark,
 /* Find mark belonging to given group in the list of marks */
 extern struct fsnotify_mark *fsnotify_find_mark(fsnotify_connp_t *connp,
 						struct fsnotify_group *group);
+/* Get cached fsid of filesystem containing object */
+extern int fsnotify_get_conn_fsid(const struct fsnotify_mark_connector *conn,
+				  __kernel_fsid_t *fsid);
 /* attach the mark to the object */
 extern int fsnotify_add_mark(struct fsnotify_mark *mark,
 			     fsnotify_connp_t *connp, unsigned int type,
-			     int allow_dups);
-extern int fsnotify_add_mark_locked(struct fsnotify_mark *mark,
-				    fsnotify_connp_t *connp, unsigned int type,
-				    int allow_dups);
+			     int allow_dups, __kernel_fsid_t *fsid);
+extern int fsnotify_add_mark_locked_fsid(struct fsnotify_mark *mark,
+					 fsnotify_connp_t *connp,
+					 unsigned int type, int allow_dups,
+					 __kernel_fsid_t *fsid);
+static inline int fsnotify_add_mark_locked(struct fsnotify_mark *mark,
+					   fsnotify_connp_t *connp,
+					   unsigned int type, int allow_dups)
+{
+	return fsnotify_add_mark_locked_fsid(mark, connp, type, allow_dups,
+					     NULL);
+}
+
 /* attach the mark to the inode */
 static inline int fsnotify_add_inode_mark(struct fsnotify_mark *mark,
 					  struct inode *inode,
 					  int allow_dups)
 {
 	return fsnotify_add_mark(mark, &inode->i_fsnotify_marks,
-				 FSNOTIFY_OBJ_TYPE_INODE, allow_dups);
+				 FSNOTIFY_OBJ_TYPE_INODE, allow_dups, NULL);
 }
 static inline int fsnotify_add_inode_mark_locked(struct fsnotify_mark *mark,
 						 struct inode *inode,
@@ -455,6 +468,7 @@ static inline int fsnotify_add_inode_mark_locked(struct fsnotify_mark *mark,
 	return fsnotify_add_mark_locked(mark, &inode->i_fsnotify_marks,
 					FSNOTIFY_OBJ_TYPE_INODE, allow_dups);
 }
+
 /* given a group and a mark, flag mark to be freed when all references are dropped */
 extern void fsnotify_destroy_mark(struct fsnotify_mark *mark,
 				  struct fsnotify_group *group);
-- 
2.17.1


^ permalink raw reply	[flat|nested] 34+ messages in thread

* [PATCH v5 11/17] vfs: add vfs_get_fsid() helper
  2019-01-10 17:04 [PATCH v5 00/17] fanotify: add support for more event types Amir Goldstein
                   ` (9 preceding siblings ...)
  2019-01-10 17:04 ` [PATCH v5 10/17] fanotify: cache fsid in fsnotify_mark_connector Amir Goldstein
@ 2019-01-10 17:04 ` Amir Goldstein
  2019-01-10 17:04 ` [PATCH v5 12/17] fanotify: use vfs_get_fsid() helper instead of vfs_statfs() Amir Goldstein
                   ` (6 subsequent siblings)
  17 siblings, 0 replies; 34+ messages in thread
From: Amir Goldstein @ 2019-01-10 17:04 UTC (permalink / raw)
  To: Jan Kara; +Cc: Matthew Bobrowski, linux-fsdevel, Al Viro

Wrapper around statfs() interface.

Cc: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Amir Goldstein <amir73il@gmail.com>
---
 fs/statfs.c            | 14 ++++++++++++++
 include/linux/statfs.h |  3 +++
 2 files changed, 17 insertions(+)

diff --git a/fs/statfs.c b/fs/statfs.c
index f0216629621d..eea7af6f2f22 100644
--- a/fs/statfs.c
+++ b/fs/statfs.c
@@ -67,6 +67,20 @@ static int statfs_by_dentry(struct dentry *dentry, struct kstatfs *buf)
 	return retval;
 }
 
+int vfs_get_fsid(struct dentry *dentry, __kernel_fsid_t *fsid)
+{
+	struct kstatfs st;
+	int error;
+
+	error = statfs_by_dentry(dentry, &st);
+	if (error)
+		return error;
+
+	*fsid = st.f_fsid;
+	return 0;
+}
+EXPORT_SYMBOL(vfs_get_fsid);
+
 int vfs_statfs(const struct path *path, struct kstatfs *buf)
 {
 	int error;
diff --git a/include/linux/statfs.h b/include/linux/statfs.h
index 3142e98546ac..9bc69edb8f18 100644
--- a/include/linux/statfs.h
+++ b/include/linux/statfs.h
@@ -41,4 +41,7 @@ struct kstatfs {
 #define ST_NODIRATIME	0x0800	/* do not update directory access times */
 #define ST_RELATIME	0x1000	/* update atime relative to mtime/ctime */
 
+struct dentry;
+extern int vfs_get_fsid(struct dentry *dentry, __kernel_fsid_t *fsid);
+
 #endif
-- 
2.17.1


^ permalink raw reply	[flat|nested] 34+ messages in thread

* [PATCH v5 12/17] fanotify: use vfs_get_fsid() helper instead of vfs_statfs()
  2019-01-10 17:04 [PATCH v5 00/17] fanotify: add support for more event types Amir Goldstein
                   ` (10 preceding siblings ...)
  2019-01-10 17:04 ` [PATCH v5 11/17] vfs: add vfs_get_fsid() helper Amir Goldstein
@ 2019-01-10 17:04 ` Amir Goldstein
  2019-01-10 17:04 ` [PATCH v5 13/17] fsnotify: report FS_ISDIR flag with MOVE_SELF and DELETE_SELF events Amir Goldstein
                   ` (5 subsequent siblings)
  17 siblings, 0 replies; 34+ messages in thread
From: Amir Goldstein @ 2019-01-10 17:04 UTC (permalink / raw)
  To: Jan Kara; +Cc: Matthew Bobrowski, linux-fsdevel

This is a cleanup that doesn't change any logic.

Signed-off-by: Amir Goldstein <amir73il@gmail.com>
---
 fs/notify/fanotify/fanotify_user.c | 25 ++++++++++---------------
 1 file changed, 10 insertions(+), 15 deletions(-)

diff --git a/fs/notify/fanotify/fanotify_user.c b/fs/notify/fanotify/fanotify_user.c
index 467e6431fbe9..4254bfedb40b 100644
--- a/fs/notify/fanotify/fanotify_user.c
+++ b/fs/notify/fanotify/fanotify_user.c
@@ -863,35 +863,31 @@ SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags)
 }
 
 /* Check if filesystem can encode a unique fid */
-static int fanotify_test_fid(struct path *path, struct kstatfs *stat)
+static int fanotify_test_fid(struct path *path, __kernel_fsid_t *fsid)
 {
-	struct kstatfs root_stat;
-	struct path root = {
-		.mnt = path->mnt,
-		.dentry = path->dentry->d_sb->s_root,
-	};
+	__kernel_fsid_t root_fsid;
 	int err;
 
 	/*
 	 * Make sure path is not in filesystem with zero fsid (e.g. tmpfs).
 	 */
-	err = vfs_statfs(path, stat);
+	err = vfs_get_fsid(path->dentry, fsid);
 	if (err)
 		return err;
 
-	if (!stat->f_fsid.val[0] && !stat->f_fsid.val[1])
+	if (!fsid->val[0] && !fsid->val[1])
 		return -ENODEV;
 
 	/*
 	 * Make sure path is not inside a filesystem subvolume (e.g. btrfs)
 	 * which uses a different fsid than sb root.
 	 */
-	err = vfs_statfs(&root, &root_stat);
+	err = vfs_get_fsid(path->dentry->d_sb->s_root, &root_fsid);
 	if (err)
 		return err;
 
-	if (root_stat.f_fsid.val[0] != stat->f_fsid.val[0] ||
-	    root_stat.f_fsid.val[1] != stat->f_fsid.val[1])
+	if (root_fsid.val[0] != fsid->val[0] ||
+	    root_fsid.val[1] != fsid->val[1])
 		return -EXDEV;
 
 	/*
@@ -916,8 +912,7 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask,
 	struct fsnotify_group *group;
 	struct fd f;
 	struct path path;
-	struct kstatfs stat;
-	__kernel_fsid_t *fsid = NULL;
+	__kernel_fsid_t __fsid, *fsid = NULL;
 	u32 valid_mask = FANOTIFY_EVENTS | FANOTIFY_EVENT_FLAGS;
 	unsigned int mark_type = flags & FANOTIFY_MARK_TYPE_BITS;
 	int ret;
@@ -996,11 +991,11 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask,
 		goto fput_and_out;
 
 	if (FAN_GROUP_FLAG(group, FAN_REPORT_FID)) {
-		ret = fanotify_test_fid(&path, &stat);
+		ret = fanotify_test_fid(&path, &__fsid);
 		if (ret)
 			goto path_put_and_out;
 
-		fsid = &stat.f_fsid;
+		fsid = &__fsid;
 	}
 
 	/* inode held in place by reference to path; group by fget on fd */
-- 
2.17.1


^ permalink raw reply	[flat|nested] 34+ messages in thread

* [PATCH v5 13/17] fsnotify: report FS_ISDIR flag with MOVE_SELF and DELETE_SELF events
  2019-01-10 17:04 [PATCH v5 00/17] fanotify: add support for more event types Amir Goldstein
                   ` (11 preceding siblings ...)
  2019-01-10 17:04 ` [PATCH v5 12/17] fanotify: use vfs_get_fsid() helper instead of vfs_statfs() Amir Goldstein
@ 2019-01-10 17:04 ` Amir Goldstein
  2019-02-07 14:57   ` Jan Kara
  2019-01-10 17:04 ` [PATCH v5 14/17] fanotify: check FS_ISDIR flag instead of d_is_dir() Amir Goldstein
                   ` (4 subsequent siblings)
  17 siblings, 1 reply; 34+ messages in thread
From: Amir Goldstein @ 2019-01-10 17:04 UTC (permalink / raw)
  To: Jan Kara; +Cc: Matthew Bobrowski, linux-fsdevel

We need to report FS_ISDIR flag with MOVE_SELF and DELETE_SELF events
for fanotify, because fanotify API requires the user to explicitly
request events on directories by FAN_ONDIR flag.

inotify never reported IN_ISDIR with those events. It looks like an
oversight, but to avoid the risk of breaking existing inotify programs,
mask the FS_ISDIR flag out when reprting those events to inotify backend.

We also add the FS_ISDIR flag with FS_ATTRIB event in the case of rename
over an empty target directory. inotify did not report IN_ISDIR in this
case, but it normally does report IN_ISDIR along with IN_ATTRIB event,
so in this case, we do not mask out the FS_ISDIR flag.

Signed-off-by: Amir Goldstein <amir73il@gmail.com>
---
 fs/notify/inotify/inotify_fsnotify.c |  9 +++++++++
 include/linux/fsnotify.h             | 23 +++++++++++++++++++----
 2 files changed, 28 insertions(+), 4 deletions(-)

diff --git a/fs/notify/inotify/inotify_fsnotify.c b/fs/notify/inotify/inotify_fsnotify.c
index fe97299975f2..ff30abd6a49b 100644
--- a/fs/notify/inotify/inotify_fsnotify.c
+++ b/fs/notify/inotify/inotify_fsnotify.c
@@ -113,6 +113,15 @@ int inotify_handle_event(struct fsnotify_group *group,
 		return -ENOMEM;
 	}
 
+	/*
+	 * We now report FS_ISDIR flag with MOVE_SELF and DELETE_SELF events
+	 * for fanotify. inotify never reported IN_ISDIR with those events.
+	 * It looks like an oversight, but to avoid the risk of breaking
+	 * existing inotify programs, mask the flag out from those events.
+	 */
+	if (mask & (IN_MOVE_SELF | IN_DELETE_SELF))
+		mask &= ~IN_ISDIR;
+
 	fsn_event = &event->fse;
 	fsnotify_init_event(fsn_event, inode);
 	event->mask = mask;
diff --git a/include/linux/fsnotify.h b/include/linux/fsnotify.h
index 116907928c7f..bec2e8f66012 100644
--- a/include/linux/fsnotify.h
+++ b/include/linux/fsnotify.h
@@ -87,7 +87,12 @@ static inline int fsnotify_perm(struct file *file, int mask)
  */
 static inline void fsnotify_link_count(struct inode *inode)
 {
-	fsnotify(inode, FS_ATTRIB, inode, FSNOTIFY_EVENT_INODE, NULL, 0);
+	__u32 mask = FS_ATTRIB;
+
+	if (S_ISDIR(inode->i_mode))
+		mask |= FS_ISDIR;
+
+	fsnotify(inode, mask, inode, FSNOTIFY_EVENT_INODE, NULL, 0);
 }
 
 /*
@@ -95,12 +100,14 @@ static inline void fsnotify_link_count(struct inode *inode)
  */
 static inline void fsnotify_move(struct inode *old_dir, struct inode *new_dir,
 				 const unsigned char *old_name,
-				 int isdir, struct inode *target, struct dentry *moved)
+				 int isdir, struct inode *target,
+				 struct dentry *moved)
 {
 	struct inode *source = moved->d_inode;
 	u32 fs_cookie = fsnotify_get_cookie();
 	__u32 old_dir_mask = FS_MOVED_FROM;
 	__u32 new_dir_mask = FS_MOVED_TO;
+	__u32 mask = FS_MOVE_SELF;
 	const unsigned char *new_name = moved->d_name.name;
 
 	if (old_dir == new_dir)
@@ -111,6 +118,9 @@ static inline void fsnotify_move(struct inode *old_dir, struct inode *new_dir,
 		new_dir_mask |= FS_ISDIR;
 	}
 
+	if (d_is_dir(moved))
+		mask |= FS_ISDIR;
+
 	fsnotify(old_dir, old_dir_mask, source, FSNOTIFY_EVENT_INODE, old_name,
 		 fs_cookie);
 	fsnotify(new_dir, new_dir_mask, source, FSNOTIFY_EVENT_INODE, new_name,
@@ -120,7 +130,7 @@ static inline void fsnotify_move(struct inode *old_dir, struct inode *new_dir,
 		fsnotify_link_count(target);
 
 	if (source)
-		fsnotify(source, FS_MOVE_SELF, moved->d_inode, FSNOTIFY_EVENT_INODE, NULL, 0);
+		fsnotify(source, mask, source, FSNOTIFY_EVENT_INODE, NULL, 0);
 	audit_inode_child(new_dir, moved, AUDIT_TYPE_CHILD_CREATE);
 }
 
@@ -197,7 +207,12 @@ static inline void fsnotify_nameremove(struct dentry *dentry, int isdir)
  */
 static inline void fsnotify_inoderemove(struct inode *inode)
 {
-	fsnotify(inode, FS_DELETE_SELF, inode, FSNOTIFY_EVENT_INODE, NULL, 0);
+	__u32 mask = FS_DELETE_SELF;
+
+	if (S_ISDIR(inode->i_mode))
+		mask |= FS_ISDIR;
+
+	fsnotify(inode, mask, inode, FSNOTIFY_EVENT_INODE, NULL, 0);
 	__fsnotify_inode_delete(inode);
 }
 
-- 
2.17.1


^ permalink raw reply	[flat|nested] 34+ messages in thread

* [PATCH v5 14/17] fanotify: check FS_ISDIR flag instead of d_is_dir()
  2019-01-10 17:04 [PATCH v5 00/17] fanotify: add support for more event types Amir Goldstein
                   ` (12 preceding siblings ...)
  2019-01-10 17:04 ` [PATCH v5 13/17] fsnotify: report FS_ISDIR flag with MOVE_SELF and DELETE_SELF events Amir Goldstein
@ 2019-01-10 17:04 ` Amir Goldstein
  2019-01-10 17:04 ` [PATCH v5 15/17] fanotify: support events with data type FSNOTIFY_EVENT_INODE Amir Goldstein
                   ` (3 subsequent siblings)
  17 siblings, 0 replies; 34+ messages in thread
From: Amir Goldstein @ 2019-01-10 17:04 UTC (permalink / raw)
  To: Jan Kara; +Cc: Matthew Bobrowski, linux-fsdevel

All fsnotify hooks set the FS_ISDIR flag for events that happen
on directory victim inodes except for fsnotify_perm().

Add the missing FS_ISDIR flag in fsnotify_perm() hook and let
fanotify_group_event_mask() check the FS_ISDIR flag instead of
checking if path argument is a directory.

This is needed for fanotify support for event types that do not
carry path information.

Signed-off-by: Amir Goldstein <amir73il@gmail.com>
---
 fs/notify/fanotify/fanotify.c | 2 +-
 include/linux/fsnotify.h      | 3 +++
 2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c
index 1bbf8b90dd83..fcb98ea99508 100644
--- a/fs/notify/fanotify/fanotify.c
+++ b/fs/notify/fanotify/fanotify.c
@@ -144,7 +144,7 @@ static u32 fanotify_group_event_mask(struct fsnotify_iter_info *iter_info,
 		marks_ignored_mask |= mark->ignored_mask;
 	}
 
-	if (d_is_dir(path->dentry) &&
+	if (event_mask & FS_ISDIR &&
 	    !(marks_mask & FS_ISDIR & ~marks_ignored_mask))
 		return 0;
 
diff --git a/include/linux/fsnotify.h b/include/linux/fsnotify.h
index bec2e8f66012..80b782d399bd 100644
--- a/include/linux/fsnotify.h
+++ b/include/linux/fsnotify.h
@@ -79,6 +79,9 @@ static inline int fsnotify_perm(struct file *file, int mask)
 		fsnotify_mask = FS_ACCESS_PERM;
 	}
 
+	if (S_ISDIR(inode->i_mode))
+		fsnotify_mask |= FS_ISDIR;
+
 	return fsnotify_path(inode, path, fsnotify_mask);
 }
 
-- 
2.17.1


^ permalink raw reply	[flat|nested] 34+ messages in thread

* [PATCH v5 15/17] fanotify: support events with data type FSNOTIFY_EVENT_INODE
  2019-01-10 17:04 [PATCH v5 00/17] fanotify: add support for more event types Amir Goldstein
                   ` (13 preceding siblings ...)
  2019-01-10 17:04 ` [PATCH v5 14/17] fanotify: check FS_ISDIR flag instead of d_is_dir() Amir Goldstein
@ 2019-01-10 17:04 ` Amir Goldstein
  2019-02-07 15:18   ` Jan Kara
  2019-01-10 17:04 ` [PATCH v5 16/17] fanotify: add support for create/attrib/move/delete events Amir Goldstein
                   ` (2 subsequent siblings)
  17 siblings, 1 reply; 34+ messages in thread
From: Amir Goldstein @ 2019-01-10 17:04 UTC (permalink / raw)
  To: Jan Kara; +Cc: Matthew Bobrowski, linux-fsdevel

When event data type is FSNOTIFY_EVENT_INODE, we don't have a refernece
to the mount, so we will not be able to open a file descriptor when user
reads the event. However, if the listener has enabled reporting file
identifier with the FAN_REPORT_FID init flag, we allow reporting those
events and we use an identifier inode to encode fid.

The inode to use as identifier when reporting fid depends on the event.
For dirent modification events, we report the modified directory inode
and we report the "victim" inode otherwise.
For example:
FS_ATTRIB reports the child inode even if reported on a watched parent.
FS_CREATE reports the modified dir inode and not the created inode.

Signed-off-by: Amir Goldstein <amir73il@gmail.com>
---
 fs/notify/fanotify/fanotify.c      | 67 ++++++++++++++++++++----------
 fs/notify/fanotify/fanotify.h      |  2 +-
 fs/notify/fanotify/fanotify_user.c |  3 +-
 3 files changed, 48 insertions(+), 24 deletions(-)

diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c
index fcb98ea99508..e3ca1632feb8 100644
--- a/fs/notify/fanotify/fanotify.c
+++ b/fs/notify/fanotify/fanotify.c
@@ -96,7 +96,7 @@ static int fanotify_get_response(struct fsnotify_group *group,
 
 	pr_debug("%s: group=%p event=%p about to return ret=%d\n", __func__,
 		 group, event, ret);
-	
+
 	return ret;
 }
 
@@ -106,9 +106,10 @@ static int fanotify_get_response(struct fsnotify_group *group,
  * been included within the event mask, but have not been explicitly
  * requested by the user, will not be present in the returned mask.
  */
-static u32 fanotify_group_event_mask(struct fsnotify_iter_info *iter_info,
-				       u32 event_mask, const void *data,
-				       int data_type)
+static u32 fanotify_group_event_mask(struct fsnotify_group *group,
+				     struct fsnotify_iter_info *iter_info,
+				     u32 event_mask, const void *data,
+				     int data_type)
 {
 	__u32 marks_mask = 0, marks_ignored_mask = 0;
 	const struct path *path = data;
@@ -118,14 +119,14 @@ static u32 fanotify_group_event_mask(struct fsnotify_iter_info *iter_info,
 	pr_debug("%s: report_mask=%x mask=%x data=%p data_type=%d\n",
 		 __func__, iter_info->report_mask, event_mask, data, data_type);
 
-	/* If we don't have enough info to send an event to userspace say no */
-	if (data_type != FSNOTIFY_EVENT_PATH)
-		return 0;
-
-	/* Sorry, fanotify only gives a damn about files and dirs */
-	if (!d_is_reg(path->dentry) &&
-	    !d_can_lookup(path->dentry))
+	if (data_type == FSNOTIFY_EVENT_PATH) {
+		/* Path type events are only relevant for files and dirs */
+		if (!d_is_reg(path->dentry) && !d_can_lookup(path->dentry))
+			return 0;
+	} else if (!FAN_GROUP_FLAG(group, FAN_REPORT_FID)) {
+		/* Events without path data require FAN_REPORT_FID */
 		return 0;
+	}
 
 	fsnotify_foreach_obj_type(type) {
 		if (!fsnotify_iter_should_report_type(iter_info, type))
@@ -153,7 +154,7 @@ static u32 fanotify_group_event_mask(struct fsnotify_iter_info *iter_info,
 }
 
 static int fanotify_encode_fid(struct fanotify_event *event,
-			       const struct path *path, gfp_t gfp,
+			       struct inode *inode, gfp_t gfp,
 			       __kernel_fsid_t *fsid)
 {
 	struct fanotify_fid *fid = &event->fid;
@@ -166,7 +167,7 @@ static int fanotify_encode_fid(struct fanotify_event *event,
 	fid->ext_fh = NULL;
 	dwords = 0;
 	err = -ENOENT;
-	type = exportfs_encode_fh(path->dentry, NULL, &dwords,  0);
+	type = exportfs_encode_inode_fh(inode, NULL, &dwords,  NULL);
 	if (!dwords)
 		goto out_err;
 
@@ -179,8 +180,8 @@ static int fanotify_encode_fid(struct fanotify_event *event,
 			goto out_err;
 	}
 
-	type = exportfs_encode_fh(path->dentry, fanotify_fid_fh(fid, bytes),
-				  &dwords,  0);
+	type = exportfs_encode_inode_fh(inode, fanotify_fid_fh(fid, bytes),
+					&dwords,  NULL);
 	err = -EINVAL;
 	if (!type || type == FILEID_INVALID || bytes != dwords << 2)
 		goto out_err;
@@ -201,13 +202,34 @@ static int fanotify_encode_fid(struct fanotify_event *event,
 	return FILEID_INVALID;
 }
 
+/*
+ * The inode to use as indentifier when reporting fid depends on the event.
+ * Report the modified directory inode on dirent modification events.
+ * Report the "victim" inode otherwise.
+ * For example:
+ * FS_ATTRIB reports the child inode even if reported on a watched parent.
+ * FS_CREATE reports the modified dir inode and not the created inode.
+ */
+static struct inode *fanotify_fid_inode(struct inode *to_tell, u32 event_mask,
+					const void *data, int data_type)
+{
+	if (event_mask & ALL_FSNOTIFY_DIRENT_EVENTS)
+		return to_tell;
+	else if (data_type == FSNOTIFY_EVENT_INODE)
+		return (struct inode *)data;
+	else if (data_type == FSNOTIFY_EVENT_PATH)
+		return d_inode(((struct path *)data)->dentry);
+	return NULL;
+}
+
 struct fanotify_event *fanotify_alloc_event(struct fsnotify_group *group,
 					    struct inode *inode, u32 mask,
-					    const struct path *path,
+					    const void *data, int data_type,
 					    __kernel_fsid_t *fsid)
 {
 	struct fanotify_event *event = NULL;
 	gfp_t gfp = GFP_KERNEL_ACCOUNT;
+	struct inode *id = fanotify_fid_inode(inode, mask, data, data_type);
 
 	/*
 	 * For queues with unlimited length lost events are not expected and
@@ -241,12 +263,12 @@ init: __maybe_unused
 	else
 		event->pid = get_pid(task_tgid(current));
 	event->fh_len = 0;
-	if (path && FAN_GROUP_FLAG(group, FAN_REPORT_FID)) {
+	if (id && FAN_GROUP_FLAG(group, FAN_REPORT_FID)) {
 		/* Report the event without a file identifier on encode error */
-		event->fh_type = fanotify_encode_fid(event, path, gfp, fsid);
-	} else if (path) {
+		event->fh_type = fanotify_encode_fid(event, id, gfp, fsid);
+	} else if (data_type == FSNOTIFY_EVENT_PATH) {
 		event->fh_type = FILEID_ROOT;
-		event->path = *path;
+		event->path = *((struct path *)data);
 		path_get(&event->path);
 	} else {
 		event->fh_type = FILEID_INVALID;
@@ -306,7 +328,8 @@ static int fanotify_handle_event(struct fsnotify_group *group,
 
 	BUILD_BUG_ON(HWEIGHT32(ALL_FANOTIFY_EVENT_BITS) != 12);
 
-	mask = fanotify_group_event_mask(iter_info, mask, data, data_type);
+	mask = fanotify_group_event_mask(group, iter_info, mask, data,
+					 data_type);
 	if (!mask)
 		return 0;
 
@@ -325,7 +348,7 @@ static int fanotify_handle_event(struct fsnotify_group *group,
 	if (FAN_GROUP_FLAG(group, FAN_REPORT_FID))
 		fsid = fanotify_get_fsid(iter_info, &__fsid);
 
-	event = fanotify_alloc_event(group, inode, mask, data, fsid);
+	event = fanotify_alloc_event(group, inode, mask, data, data_type, fsid);
 	ret = -ENOMEM;
 	if (unlikely(!event)) {
 		/*
diff --git a/fs/notify/fanotify/fanotify.h b/fs/notify/fanotify/fanotify.h
index 5b072afa4e19..e84d68c6840a 100644
--- a/fs/notify/fanotify/fanotify.h
+++ b/fs/notify/fanotify/fanotify.h
@@ -132,5 +132,5 @@ static inline struct fanotify_event *FANOTIFY_E(struct fsnotify_event *fse)
 
 struct fanotify_event *fanotify_alloc_event(struct fsnotify_group *group,
 					    struct inode *inode, u32 mask,
-					    const struct path *path,
+					    const void *data, int data_type,
 					    __kernel_fsid_t *fsid);
diff --git a/fs/notify/fanotify/fanotify_user.c b/fs/notify/fanotify/fanotify_user.c
index 4254bfedb40b..8ac3ebc7b5ed 100644
--- a/fs/notify/fanotify/fanotify_user.c
+++ b/fs/notify/fanotify/fanotify_user.c
@@ -800,7 +800,8 @@ SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags)
 	atomic_inc(&user->fanotify_listeners);
 	group->memcg = get_mem_cgroup_from_mm(current->mm);
 
-	oevent = fanotify_alloc_event(group, NULL, FS_Q_OVERFLOW, NULL, NULL);
+	oevent = fanotify_alloc_event(group, NULL, FS_Q_OVERFLOW, NULL,
+				      FSNOTIFY_EVENT_NONE, NULL);
 	if (unlikely(!oevent)) {
 		fd = -ENOMEM;
 		goto out_destroy_group;
-- 
2.17.1


^ permalink raw reply	[flat|nested] 34+ messages in thread

* [PATCH v5 16/17] fanotify: add support for create/attrib/move/delete events
  2019-01-10 17:04 [PATCH v5 00/17] fanotify: add support for more event types Amir Goldstein
                   ` (14 preceding siblings ...)
  2019-01-10 17:04 ` [PATCH v5 15/17] fanotify: support events with data type FSNOTIFY_EVENT_INODE Amir Goldstein
@ 2019-01-10 17:04 ` Amir Goldstein
  2019-01-10 17:04 ` [PATCH v5 17/17] fanotify: report FAN_ONDIR to listener with FAN_REPORT_FID Amir Goldstein
  2019-02-07 16:26 ` [PATCH v5 00/17] fanotify: add support for more event types Jan Kara
  17 siblings, 0 replies; 34+ messages in thread
From: Amir Goldstein @ 2019-01-10 17:04 UTC (permalink / raw)
  To: Jan Kara; +Cc: Matthew Bobrowski, linux-fsdevel, linux-api

Add support for events with data type FSNOTIFY_EVENT_INODE
(e.g. create/attrib/move/delete) for inode and filesystem mark types.

The "inode" events do not carry enough information (i.e. path) to
report event->fd, so we do not allow setting a mask for those events
unless group supports reporting fid.

The "inode" events are not supported on a mount mark, because they do
not carry enough information (i.e. path) to be filtered by mount point.

The "dirent" events (create/move/delete) report the fid of the parent
directory where events took place without specifying the filename of the
child. In the future, fanotify may get support for reporting filename
information for those events.

Cc: <linux-api@vger.kernel.org>
Signed-off-by: Amir Goldstein <amir73il@gmail.com>
---
 fs/notify/fanotify/fanotify.c      |  9 ++++++++-
 fs/notify/fanotify/fanotify_user.c | 12 ++++++++++++
 include/linux/fanotify.h           | 22 ++++++++++++++++++++--
 include/uapi/linux/fanotify.h      |  8 ++++++++
 4 files changed, 48 insertions(+), 3 deletions(-)

diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c
index e3ca1632feb8..4ba9c2233965 100644
--- a/fs/notify/fanotify/fanotify.c
+++ b/fs/notify/fanotify/fanotify.c
@@ -315,9 +315,16 @@ static int fanotify_handle_event(struct fsnotify_group *group,
 
 	BUILD_BUG_ON(FAN_ACCESS != FS_ACCESS);
 	BUILD_BUG_ON(FAN_MODIFY != FS_MODIFY);
+	BUILD_BUG_ON(FAN_ATTRIB != FS_ATTRIB);
 	BUILD_BUG_ON(FAN_CLOSE_NOWRITE != FS_CLOSE_NOWRITE);
 	BUILD_BUG_ON(FAN_CLOSE_WRITE != FS_CLOSE_WRITE);
 	BUILD_BUG_ON(FAN_OPEN != FS_OPEN);
+	BUILD_BUG_ON(FAN_MOVED_TO != FS_MOVED_TO);
+	BUILD_BUG_ON(FAN_MOVED_FROM != FS_MOVED_FROM);
+	BUILD_BUG_ON(FAN_CREATE != FS_CREATE);
+	BUILD_BUG_ON(FAN_DELETE != FS_DELETE);
+	BUILD_BUG_ON(FAN_DELETE_SELF != FS_DELETE_SELF);
+	BUILD_BUG_ON(FAN_MOVE_SELF != FS_MOVE_SELF);
 	BUILD_BUG_ON(FAN_EVENT_ON_CHILD != FS_EVENT_ON_CHILD);
 	BUILD_BUG_ON(FAN_Q_OVERFLOW != FS_Q_OVERFLOW);
 	BUILD_BUG_ON(FAN_OPEN_PERM != FS_OPEN_PERM);
@@ -326,7 +333,7 @@ static int fanotify_handle_event(struct fsnotify_group *group,
 	BUILD_BUG_ON(FAN_OPEN_EXEC != FS_OPEN_EXEC);
 	BUILD_BUG_ON(FAN_OPEN_EXEC_PERM != FS_OPEN_EXEC_PERM);
 
-	BUILD_BUG_ON(HWEIGHT32(ALL_FANOTIFY_EVENT_BITS) != 12);
+	BUILD_BUG_ON(HWEIGHT32(ALL_FANOTIFY_EVENT_BITS) != 19);
 
 	mask = fanotify_group_event_mask(group, iter_info, mask, data,
 					 data_type);
diff --git a/fs/notify/fanotify/fanotify_user.c b/fs/notify/fanotify/fanotify_user.c
index 8ac3ebc7b5ed..4ef6002072cc 100644
--- a/fs/notify/fanotify/fanotify_user.c
+++ b/fs/notify/fanotify/fanotify_user.c
@@ -976,6 +976,18 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask,
 	    group->priority == FS_PRIO_0)
 		goto fput_and_out;
 
+	/*
+	 * Events with data type inode do not carry enough information to report
+	 * event->fd, so we do not allow setting a mask for inode events unless
+	 * group supports reporting fid.
+	 * inode events are not supported on a mount mark, because they do not
+	 * carry enough information (i.e. path) to be filtered by mount point.
+	 */
+	if (mask & FANOTIFY_INODE_EVENTS &&
+	    (!FAN_GROUP_FLAG(group, FAN_REPORT_FID) ||
+	     mark_type == FAN_MARK_MOUNT))
+		goto fput_and_out;
+
 	if (flags & FAN_MARK_FLUSH) {
 		ret = 0;
 		if (mark_type == FAN_MARK_MOUNT)
diff --git a/include/linux/fanotify.h b/include/linux/fanotify.h
index f59be967f72b..e9d45387089f 100644
--- a/include/linux/fanotify.h
+++ b/include/linux/fanotify.h
@@ -35,10 +35,28 @@
 				 FAN_MARK_IGNORED_SURV_MODIFY | \
 				 FAN_MARK_FLUSH)
 
-/* Events that user can request to be notified on */
-#define FANOTIFY_EVENTS		(FAN_ACCESS | FAN_MODIFY | \
+/*
+ * Events that can be reported with data type FSNOTIFY_EVENT_PATH.
+ * Note that FAN_MODIFY can also be reported with data type
+ * FSNOTIFY_EVENT_INODE.
+ */
+#define FANOTIFY_PATH_EVENTS	(FAN_ACCESS | FAN_MODIFY | \
 				 FAN_CLOSE | FAN_OPEN | FAN_OPEN_EXEC)
 
+/*
+ * Directory entry modification events - reported only to directory
+ * where entry is modified and not to a watching parent.
+ */
+#define FANOTIFY_DIRENT_EVENTS	(FAN_MOVE | FAN_CREATE | FAN_DELETE)
+
+/* Events that can only be reported with data type FSNOTIFY_EVENT_INODE */
+#define FANOTIFY_INODE_EVENTS	(FANOTIFY_DIRENT_EVENTS | \
+				 FAN_ATTRIB | FAN_MOVE_SELF | FAN_DELETE_SELF)
+
+/* Events that user can request to be notified on */
+#define FANOTIFY_EVENTS		(FANOTIFY_PATH_EVENTS | \
+				 FANOTIFY_INODE_EVENTS)
+
 /* Events that require a permission response from user */
 #define FANOTIFY_PERM_EVENTS	(FAN_OPEN_PERM | FAN_ACCESS_PERM | \
 				 FAN_OPEN_EXEC_PERM)
diff --git a/include/uapi/linux/fanotify.h b/include/uapi/linux/fanotify.h
index 959ae2bdc7ca..b9effa6f8503 100644
--- a/include/uapi/linux/fanotify.h
+++ b/include/uapi/linux/fanotify.h
@@ -7,9 +7,16 @@
 /* the following events that user-space can register for */
 #define FAN_ACCESS		0x00000001	/* File was accessed */
 #define FAN_MODIFY		0x00000002	/* File was modified */
+#define FAN_ATTRIB		0x00000004	/* Metadata changed */
 #define FAN_CLOSE_WRITE		0x00000008	/* Writtable file closed */
 #define FAN_CLOSE_NOWRITE	0x00000010	/* Unwrittable file closed */
 #define FAN_OPEN		0x00000020	/* File was opened */
+#define FAN_MOVED_FROM		0x00000040	/* File was moved from X */
+#define FAN_MOVED_TO		0x00000080	/* File was moved to Y */
+#define FAN_CREATE		0x00000100	/* Subfile was created */
+#define FAN_DELETE		0x00000200	/* Subfile was deleted */
+#define FAN_DELETE_SELF		0x00000400	/* Self was deleted */
+#define FAN_MOVE_SELF		0x00000800	/* Self was moved */
 #define FAN_OPEN_EXEC		0x00001000	/* File was opened for exec */
 
 #define FAN_Q_OVERFLOW		0x00004000	/* Event queued overflowed */
@@ -24,6 +31,7 @@
 
 /* helper events */
 #define FAN_CLOSE		(FAN_CLOSE_WRITE | FAN_CLOSE_NOWRITE) /* close */
+#define FAN_MOVE		(FAN_MOVED_FROM | FAN_MOVED_TO) /* moves */
 
 /* flags used for fanotify_init() */
 #define FAN_CLOEXEC		0x00000001
-- 
2.17.1


^ permalink raw reply	[flat|nested] 34+ messages in thread

* [PATCH v5 17/17] fanotify: report FAN_ONDIR to listener with FAN_REPORT_FID
  2019-01-10 17:04 [PATCH v5 00/17] fanotify: add support for more event types Amir Goldstein
                   ` (15 preceding siblings ...)
  2019-01-10 17:04 ` [PATCH v5 16/17] fanotify: add support for create/attrib/move/delete events Amir Goldstein
@ 2019-01-10 17:04 ` Amir Goldstein
  2019-02-07 16:26 ` [PATCH v5 00/17] fanotify: add support for more event types Jan Kara
  17 siblings, 0 replies; 34+ messages in thread
From: Amir Goldstein @ 2019-01-10 17:04 UTC (permalink / raw)
  To: Jan Kara; +Cc: Matthew Bobrowski, linux-fsdevel, linux-api

dirent modification events (create/delete/move) do not carry the
child entry name/inode information. Instead, we report FAN_ONDIR
for mkdir/rmdir so user can differentiate them from creat/unlink.

This is consistent with inotify reporting IN_ISDIR with dirent events
and is useful for implementing recursive directory tree watcher.

We avoid merging dirent events referring to subdirs with dirent events
referring to non subdirs, otherwise, user won't be able to tell from a
mask FAN_CREATE|FAN_DELETE|FAN_ONDIR if it describes mkdir+unlink pair
or rmdir+create pair of events.

For backward compatibility and consistency, do not report FAN_ONDIR
to user in legacy fanotify mode (reporting fd) and report FAN_ONDIR
to user in FAN_REPORT_FID mode for all event types.

Cc: <linux-api@vger.kernel.org>
Signed-off-by: Amir Goldstein <amir73il@gmail.com>
---
 fs/notify/fanotify/fanotify.c | 34 +++++++++++++++++++++++++++++++---
 include/linux/fanotify.h      |  2 +-
 2 files changed, 32 insertions(+), 4 deletions(-)

diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c
index 4ba9c2233965..8ccca3cd866a 100644
--- a/fs/notify/fanotify/fanotify.c
+++ b/fs/notify/fanotify/fanotify.c
@@ -34,7 +34,16 @@ static bool should_merge(struct fsnotify_event *old_fsn,
 		return old->path.mnt == new->path.mnt &&
 			old->path.dentry == new->path.dentry;
 	} else if (fanotify_event_has_fid(old)) {
-		return fanotify_fid_equal(&old->fid, &new->fid, old->fh_len);
+		/*
+		 * We want to merge many dirent events in the same dir (i.e.
+		 * creates/unlinks/renames), but we do not want to merge dirent
+		 * events referring to subdirs with dirent events referring to
+		 * non subdirs, otherwise, user won't be able to tell from a
+		 * mask FAN_CREATE|FAN_DELETE|FAN_ONDIR if it describes mkdir+
+		 * unlink pair or rmdir+create pair of events.
+		 */
+		return (old->mask & FS_ISDIR) == (new->mask & FS_ISDIR) &&
+			fanotify_fid_equal(&old->fid, &new->fid, old->fh_len);
 	}
 
 	/* Do not merge events if we failed to encode fid */
@@ -112,6 +121,7 @@ static u32 fanotify_group_event_mask(struct fsnotify_group *group,
 				     int data_type)
 {
 	__u32 marks_mask = 0, marks_ignored_mask = 0;
+	__u32 test_mask, user_mask = FANOTIFY_OUTGOING_EVENTS;
 	const struct path *path = data;
 	struct fsnotify_mark *mark;
 	int type;
@@ -145,12 +155,30 @@ static u32 fanotify_group_event_mask(struct fsnotify_group *group,
 		marks_ignored_mask |= mark->ignored_mask;
 	}
 
+	test_mask = event_mask & marks_mask & ~marks_ignored_mask;
+
+	/*
+	 * dirent modification events (create/delete/move) do not carry the
+	 * child entry name/inode information. Instead, we report FAN_ONDIR
+	 * for mkdir/rmdir so user can differentiate them from creat/unlink.
+	 *
+	 * For backward compatibility and consistency, do not report FAN_ONDIR
+	 * to user in legacy fanotify mode (reporting fd) and report FAN_ONDIR
+	 * to user in FAN_REPORT_FID mode for all event types.
+	 */
+	if (FAN_GROUP_FLAG(group, FAN_REPORT_FID)) {
+		/* Do not report FAN_ONDIR without any event */
+		if (!(test_mask & ~FAN_ONDIR))
+			return 0;
+	} else {
+		user_mask &= ~FAN_ONDIR;
+	}
+
 	if (event_mask & FS_ISDIR &&
 	    !(marks_mask & FS_ISDIR & ~marks_ignored_mask))
 		return 0;
 
-	return event_mask & FANOTIFY_OUTGOING_EVENTS & marks_mask &
-		~marks_ignored_mask;
+	return test_mask & user_mask;
 }
 
 static int fanotify_encode_fid(struct fanotify_event *event,
diff --git a/include/linux/fanotify.h b/include/linux/fanotify.h
index e9d45387089f..b79fa9bb7359 100644
--- a/include/linux/fanotify.h
+++ b/include/linux/fanotify.h
@@ -67,7 +67,7 @@
 /* Events that may be reported to user */
 #define FANOTIFY_OUTGOING_EVENTS	(FANOTIFY_EVENTS | \
 					 FANOTIFY_PERM_EVENTS | \
-					 FAN_Q_OVERFLOW)
+					 FAN_Q_OVERFLOW | FAN_ONDIR)
 
 #define ALL_FANOTIFY_EVENT_BITS		(FANOTIFY_OUTGOING_EVENTS | \
 					 FANOTIFY_EVENT_FLAGS)
-- 
2.17.1


^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH v5 10/17] fanotify: cache fsid in fsnotify_mark_connector
  2019-01-10 17:04 ` [PATCH v5 10/17] fanotify: cache fsid in fsnotify_mark_connector Amir Goldstein
@ 2019-01-11  3:13   ` kbuild test robot
  2019-01-14  7:30   ` Dan Carpenter
  2019-02-07 14:48   ` Jan Kara
  2 siblings, 0 replies; 34+ messages in thread
From: kbuild test robot @ 2019-01-11  3:13 UTC (permalink / raw)
  To: Amir Goldstein; +Cc: kbuild-all, Jan Kara, Matthew Bobrowski, linux-fsdevel

[-- Attachment #1: Type: text/plain, Size: 16284 bytes --]

Hi Amir,

I love your patch! Perhaps something to improve:

[auto build test WARNING on linus/master]
[also build test WARNING on v5.0-rc1 next-20190110]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Amir-Goldstein/fanotify-add-support-for-more-event-types/20190111-090241
config: mips-loongson1c_defconfig (attached as .config)
compiler: mipsel-linux-gnu-gcc (Debian 7.2.0-11) 7.2.0
reproduce:
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        GCC_VERSION=7.2.0 make.cross ARCH=mips 

All warnings (new ones prefixed by >>):

   In file included from include/linux/kernel.h:14:0,
                    from include/linux/list.h:9,
                    from include/linux/wait.h:7,
                    from include/linux/wait_bit.h:8,
                    from include/linux/fs.h:6,
                    from fs/notify/mark.c:76:
   fs/notify/mark.c: In function 'fsnotify_add_mark_list':
>> include/linux/kern_levels.h:5:18: warning: format '%x' expects argument of type 'unsigned int', but argument 4 has type 'long int' [-Wformat=]
    #define KERN_SOH "\001"  /* ASCII Start Of Header */
                     ^
   include/linux/printk.h:424:10: note: in definition of macro 'printk_ratelimited'
      printk(fmt, ##__VA_ARGS__);    \
             ^~~
   include/linux/kern_levels.h:12:22: note: in expansion of macro 'KERN_SOH'
    #define KERN_WARNING KERN_SOH "4" /* warning conditions */
                         ^~~~~~~~
   include/linux/printk.h:440:21: note: in expansion of macro 'KERN_WARNING'
     printk_ratelimited(KERN_WARNING pr_fmt(fmt), ##__VA_ARGS__)
                        ^~~~~~~~~~~~
>> fs/notify/mark.c:587:3: note: in expansion of macro 'pr_warn_ratelimited'
      pr_warn_ratelimited("%s: fsid mismatch on object of type %u: %x.%x != %x.%x\n",
      ^~~~~~~~~~~~~~~~~~~
   fs/notify/mark.c:587:65: note: format string is defined here
      pr_warn_ratelimited("%s: fsid mismatch on object of type %u: %x.%x != %x.%x\n",
                                                                   ~^
                                                                   %lx
   In file included from include/linux/kernel.h:14:0,
                    from include/linux/list.h:9,
                    from include/linux/wait.h:7,
                    from include/linux/wait_bit.h:8,
                    from include/linux/fs.h:6,
                    from fs/notify/mark.c:76:
   include/linux/kern_levels.h:5:18: warning: format '%x' expects argument of type 'unsigned int', but argument 5 has type 'long int' [-Wformat=]
    #define KERN_SOH "\001"  /* ASCII Start Of Header */
                     ^
   include/linux/printk.h:424:10: note: in definition of macro 'printk_ratelimited'
      printk(fmt, ##__VA_ARGS__);    \
             ^~~
   include/linux/kern_levels.h:12:22: note: in expansion of macro 'KERN_SOH'
    #define KERN_WARNING KERN_SOH "4" /* warning conditions */
                         ^~~~~~~~
   include/linux/printk.h:440:21: note: in expansion of macro 'KERN_WARNING'
     printk_ratelimited(KERN_WARNING pr_fmt(fmt), ##__VA_ARGS__)
                        ^~~~~~~~~~~~
>> fs/notify/mark.c:587:3: note: in expansion of macro 'pr_warn_ratelimited'
      pr_warn_ratelimited("%s: fsid mismatch on object of type %u: %x.%x != %x.%x\n",
      ^~~~~~~~~~~~~~~~~~~
   fs/notify/mark.c:587:68: note: format string is defined here
      pr_warn_ratelimited("%s: fsid mismatch on object of type %u: %x.%x != %x.%x\n",
                                                                      ~^
                                                                      %lx
   In file included from include/linux/kernel.h:14:0,
                    from include/linux/list.h:9,
                    from include/linux/wait.h:7,
                    from include/linux/wait_bit.h:8,
                    from include/linux/fs.h:6,
                    from fs/notify/mark.c:76:
   include/linux/kern_levels.h:5:18: warning: format '%x' expects argument of type 'unsigned int', but argument 6 has type 'long int' [-Wformat=]
    #define KERN_SOH "\001"  /* ASCII Start Of Header */
                     ^
   include/linux/printk.h:424:10: note: in definition of macro 'printk_ratelimited'
      printk(fmt, ##__VA_ARGS__);    \
             ^~~
   include/linux/kern_levels.h:12:22: note: in expansion of macro 'KERN_SOH'
    #define KERN_WARNING KERN_SOH "4" /* warning conditions */
                         ^~~~~~~~
   include/linux/printk.h:440:21: note: in expansion of macro 'KERN_WARNING'
     printk_ratelimited(KERN_WARNING pr_fmt(fmt), ##__VA_ARGS__)
                        ^~~~~~~~~~~~
>> fs/notify/mark.c:587:3: note: in expansion of macro 'pr_warn_ratelimited'
      pr_warn_ratelimited("%s: fsid mismatch on object of type %u: %x.%x != %x.%x\n",
      ^~~~~~~~~~~~~~~~~~~
   fs/notify/mark.c:587:74: note: format string is defined here
      pr_warn_ratelimited("%s: fsid mismatch on object of type %u: %x.%x != %x.%x\n",
                                                                            ~^
                                                                            %lx
   In file included from include/linux/kernel.h:14:0,
                    from include/linux/list.h:9,
                    from include/linux/wait.h:7,
                    from include/linux/wait_bit.h:8,
                    from include/linux/fs.h:6,
                    from fs/notify/mark.c:76:
   include/linux/kern_levels.h:5:18: warning: format '%x' expects argument of type 'unsigned int', but argument 7 has type 'long int' [-Wformat=]
    #define KERN_SOH "\001"  /* ASCII Start Of Header */
                     ^
   include/linux/printk.h:424:10: note: in definition of macro 'printk_ratelimited'
      printk(fmt, ##__VA_ARGS__);    \
             ^~~
   include/linux/kern_levels.h:12:22: note: in expansion of macro 'KERN_SOH'
    #define KERN_WARNING KERN_SOH "4" /* warning conditions */
                         ^~~~~~~~
   include/linux/printk.h:440:21: note: in expansion of macro 'KERN_WARNING'
     printk_ratelimited(KERN_WARNING pr_fmt(fmt), ##__VA_ARGS__)
                        ^~~~~~~~~~~~
>> fs/notify/mark.c:587:3: note: in expansion of macro 'pr_warn_ratelimited'
      pr_warn_ratelimited("%s: fsid mismatch on object of type %u: %x.%x != %x.%x\n",
      ^~~~~~~~~~~~~~~~~~~
   fs/notify/mark.c:587:77: note: format string is defined here
      pr_warn_ratelimited("%s: fsid mismatch on object of type %u: %x.%x != %x.%x\n",
                                                                               ~^
                                                                               %lx
--
   In file included from include/linux/kernel.h:14:0,
                    from include/linux/list.h:9,
                    from include/linux/wait.h:7,
                    from include/linux/wait_bit.h:8,
                    from include/linux/fs.h:6,
                    from fs//notify/mark.c:76:
   fs//notify/mark.c: In function 'fsnotify_add_mark_list':
>> include/linux/kern_levels.h:5:18: warning: format '%x' expects argument of type 'unsigned int', but argument 4 has type 'long int' [-Wformat=]
    #define KERN_SOH "\001"  /* ASCII Start Of Header */
                     ^
   include/linux/printk.h:424:10: note: in definition of macro 'printk_ratelimited'
      printk(fmt, ##__VA_ARGS__);    \
             ^~~
   include/linux/kern_levels.h:12:22: note: in expansion of macro 'KERN_SOH'
    #define KERN_WARNING KERN_SOH "4" /* warning conditions */
                         ^~~~~~~~
   include/linux/printk.h:440:21: note: in expansion of macro 'KERN_WARNING'
     printk_ratelimited(KERN_WARNING pr_fmt(fmt), ##__VA_ARGS__)
                        ^~~~~~~~~~~~
   fs//notify/mark.c:587:3: note: in expansion of macro 'pr_warn_ratelimited'
      pr_warn_ratelimited("%s: fsid mismatch on object of type %u: %x.%x != %x.%x\n",
      ^~~~~~~~~~~~~~~~~~~
   fs//notify/mark.c:587:65: note: format string is defined here
      pr_warn_ratelimited("%s: fsid mismatch on object of type %u: %x.%x != %x.%x\n",
                                                                   ~^
                                                                   %lx
   In file included from include/linux/kernel.h:14:0,
                    from include/linux/list.h:9,
                    from include/linux/wait.h:7,
                    from include/linux/wait_bit.h:8,
                    from include/linux/fs.h:6,
                    from fs//notify/mark.c:76:
   include/linux/kern_levels.h:5:18: warning: format '%x' expects argument of type 'unsigned int', but argument 5 has type 'long int' [-Wformat=]
    #define KERN_SOH "\001"  /* ASCII Start Of Header */
                     ^
   include/linux/printk.h:424:10: note: in definition of macro 'printk_ratelimited'
      printk(fmt, ##__VA_ARGS__);    \
             ^~~
   include/linux/kern_levels.h:12:22: note: in expansion of macro 'KERN_SOH'
    #define KERN_WARNING KERN_SOH "4" /* warning conditions */
                         ^~~~~~~~
   include/linux/printk.h:440:21: note: in expansion of macro 'KERN_WARNING'
     printk_ratelimited(KERN_WARNING pr_fmt(fmt), ##__VA_ARGS__)
                        ^~~~~~~~~~~~
   fs//notify/mark.c:587:3: note: in expansion of macro 'pr_warn_ratelimited'
      pr_warn_ratelimited("%s: fsid mismatch on object of type %u: %x.%x != %x.%x\n",
      ^~~~~~~~~~~~~~~~~~~
   fs//notify/mark.c:587:68: note: format string is defined here
      pr_warn_ratelimited("%s: fsid mismatch on object of type %u: %x.%x != %x.%x\n",
                                                                      ~^
                                                                      %lx
   In file included from include/linux/kernel.h:14:0,
                    from include/linux/list.h:9,
                    from include/linux/wait.h:7,
                    from include/linux/wait_bit.h:8,
                    from include/linux/fs.h:6,
                    from fs//notify/mark.c:76:
   include/linux/kern_levels.h:5:18: warning: format '%x' expects argument of type 'unsigned int', but argument 6 has type 'long int' [-Wformat=]
    #define KERN_SOH "\001"  /* ASCII Start Of Header */
                     ^
   include/linux/printk.h:424:10: note: in definition of macro 'printk_ratelimited'
      printk(fmt, ##__VA_ARGS__);    \
             ^~~
   include/linux/kern_levels.h:12:22: note: in expansion of macro 'KERN_SOH'
    #define KERN_WARNING KERN_SOH "4" /* warning conditions */
                         ^~~~~~~~
   include/linux/printk.h:440:21: note: in expansion of macro 'KERN_WARNING'
     printk_ratelimited(KERN_WARNING pr_fmt(fmt), ##__VA_ARGS__)
                        ^~~~~~~~~~~~
   fs//notify/mark.c:587:3: note: in expansion of macro 'pr_warn_ratelimited'
      pr_warn_ratelimited("%s: fsid mismatch on object of type %u: %x.%x != %x.%x\n",
      ^~~~~~~~~~~~~~~~~~~
   fs//notify/mark.c:587:74: note: format string is defined here
      pr_warn_ratelimited("%s: fsid mismatch on object of type %u: %x.%x != %x.%x\n",
                                                                            ~^
                                                                            %lx
   In file included from include/linux/kernel.h:14:0,
                    from include/linux/list.h:9,
                    from include/linux/wait.h:7,
                    from include/linux/wait_bit.h:8,
                    from include/linux/fs.h:6,
                    from fs//notify/mark.c:76:
   include/linux/kern_levels.h:5:18: warning: format '%x' expects argument of type 'unsigned int', but argument 7 has type 'long int' [-Wformat=]
    #define KERN_SOH "\001"  /* ASCII Start Of Header */
                     ^
   include/linux/printk.h:424:10: note: in definition of macro 'printk_ratelimited'
      printk(fmt, ##__VA_ARGS__);    \
             ^~~
   include/linux/kern_levels.h:12:22: note: in expansion of macro 'KERN_SOH'
    #define KERN_WARNING KERN_SOH "4" /* warning conditions */
                         ^~~~~~~~
   include/linux/printk.h:440:21: note: in expansion of macro 'KERN_WARNING'
     printk_ratelimited(KERN_WARNING pr_fmt(fmt), ##__VA_ARGS__)
                        ^~~~~~~~~~~~
   fs//notify/mark.c:587:3: note: in expansion of macro 'pr_warn_ratelimited'
      pr_warn_ratelimited("%s: fsid mismatch on object of type %u: %x.%x != %x.%x\n",
      ^~~~~~~~~~~~~~~~~~~
   fs//notify/mark.c:587:77: note: format string is defined here
      pr_warn_ratelimited("%s: fsid mismatch on object of type %u: %x.%x != %x.%x\n",
                                                                               ~^
                                                                               %lx

vim +/pr_warn_ratelimited +587 fs/notify/mark.c

   545	
   546	/*
   547	 * Add mark into proper place in given list of marks. These marks may be used
   548	 * for the fsnotify backend to determine which event types should be delivered
   549	 * to which group and for which inodes. These marks are ordered according to
   550	 * priority, highest number first, and then by the group's location in memory.
   551	 */
   552	static int fsnotify_add_mark_list(struct fsnotify_mark *mark,
   553					  fsnotify_connp_t *connp, unsigned int type,
   554					  int allow_dups, __kernel_fsid_t *fsid)
   555	{
   556		struct fsnotify_mark *lmark, *last = NULL;
   557		struct fsnotify_mark_connector *conn;
   558		int cmp;
   559		int err = 0;
   560	
   561		if (WARN_ON(!fsnotify_valid_obj_type(type)))
   562			return -EINVAL;
   563	
   564		/* Backend is expected to check for zero fsid (e.g. tmpfs) */
   565		if (fsid && WARN_ON_ONCE(!fsid->val[0] && !fsid->val[1]))
   566			return -ENODEV;
   567	
   568	restart:
   569		spin_lock(&mark->lock);
   570		conn = fsnotify_grab_connector(connp);
   571		if (!conn) {
   572			spin_unlock(&mark->lock);
   573			err = fsnotify_attach_connector_to_object(connp, type, fsid);
   574			if (err)
   575				return err;
   576			goto restart;
   577		} else if (fsid && (conn->fsid.val[0] || conn->fsid.val[1]) &&
   578			   (fsid->val[0] != conn->fsid.val[0] ||
   579			    fsid->val[1] != conn->fsid.val[1])) {
   580			/*
   581			 * Backend is expected to check for non uniform fsid
   582			 * (e.g. btrfs), but maybe we missed something?
   583			 * Only allow setting conn->fsid once to non zero fsid.
   584			 * inotify and non-fid fanotify groups do not set nor test
   585			 * conn->fsid.
   586			 */
 > 587			pr_warn_ratelimited("%s: fsid mismatch on object of type %u: %x.%x != %x.%x\n",
   588					    __func__, conn->type,
   589					    fsid->val[0], fsid->val[1],
   590					    conn->fsid.val[0], conn->fsid.val[1]);
   591			err = -EXDEV;
   592			goto out_err;
   593		}
   594	
   595		/* is mark the first mark? */
   596		if (hlist_empty(&conn->list)) {
   597			hlist_add_head_rcu(&mark->obj_list, &conn->list);
   598			goto added;
   599		}
   600	
   601		/* should mark be in the middle of the current list? */
   602		hlist_for_each_entry(lmark, &conn->list, obj_list) {
   603			last = lmark;
   604	
   605			if ((lmark->group == mark->group) &&
   606			    (lmark->flags & FSNOTIFY_MARK_FLAG_ATTACHED) &&
   607			    !allow_dups) {
   608				err = -EEXIST;
   609				goto out_err;
   610			}
   611	
   612			cmp = fsnotify_compare_groups(lmark->group, mark->group);
   613			if (cmp >= 0) {
   614				hlist_add_before_rcu(&mark->obj_list, &lmark->obj_list);
   615				goto added;
   616			}
   617		}
   618	
   619		BUG_ON(last == NULL);
   620		/* mark should be the last entry.  last is the current last entry */
   621		hlist_add_behind_rcu(&mark->obj_list, &last->obj_list);
   622	added:
   623		mark->connector = conn;
   624	out_err:
   625		spin_unlock(&conn->lock);
   626		spin_unlock(&mark->lock);
   627		return err;
   628	}
   629	

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 13190 bytes --]

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH v5 07/17] fanotify: encode file identifier for FAN_REPORT_FID
  2019-01-10 17:04 ` [PATCH v5 07/17] fanotify: encode file identifier for FAN_REPORT_FID Amir Goldstein
@ 2019-01-11  8:10   ` kbuild test robot
  2019-01-11  8:37     ` Amir Goldstein
  0 siblings, 1 reply; 34+ messages in thread
From: kbuild test robot @ 2019-01-11  8:10 UTC (permalink / raw)
  To: Amir Goldstein; +Cc: kbuild-all, Jan Kara, Matthew Bobrowski, linux-fsdevel

[-- Attachment #1: Type: text/plain, Size: 5760 bytes --]

Hi Amir,

I love your patch! Perhaps something to improve:

[auto build test WARNING on linus/master]
[also build test WARNING on v5.0-rc1]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Amir-Goldstein/fanotify-add-support-for-more-event-types/20190111-090241
config: mips-allmodconfig (attached as .config)
compiler: mips-linux-gnu-gcc (Debian 7.2.0-11) 7.2.0
reproduce:
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        GCC_VERSION=7.2.0 make.cross ARCH=mips 

All warnings (new ones prefixed by >>):

   In file included from include/linux/kernel.h:14:0,
                    from include/linux/list.h:9,
                    from include/linux/preempt.h:11,
                    from include/linux/spinlock.h:51,
                    from include/linux/fdtable.h:11,
                    from fs/notify/fanotify/fanotify.c:3:
   fs/notify/fanotify/fanotify.c: In function 'fanotify_encode_fid':
   include/linux/kern_levels.h:5:18: warning: format '%x' expects argument of type 'unsigned int', but argument 2 has type 'long int' [-Wformat=]
    #define KERN_SOH "\001"  /* ASCII Start Of Header */
                     ^
   include/linux/printk.h:424:10: note: in definition of macro 'printk_ratelimited'
      printk(fmt, ##__VA_ARGS__);    \
             ^~~
   include/linux/kern_levels.h:12:22: note: in expansion of macro 'KERN_SOH'
    #define KERN_WARNING KERN_SOH "4" /* warning conditions */
                         ^~~~~~~~
   include/linux/printk.h:440:21: note: in expansion of macro 'KERN_WARNING'
     printk_ratelimited(KERN_WARNING pr_fmt(fmt), ##__VA_ARGS__)
                        ^~~~~~~~~~~~
>> fs/notify/fanotify/fanotify.c:196:2: note: in expansion of macro 'pr_warn_ratelimited'
     pr_warn_ratelimited("fanotify: failed to encode fid (fsid=%x.%x, type=%d, bytes=%d, err=%i)\n",
     ^~~~~~~~~~~~~~~~~~~
   fs/notify/fanotify/fanotify.c:196:61: note: format string is defined here
     pr_warn_ratelimited("fanotify: failed to encode fid (fsid=%x.%x, type=%d, bytes=%d, err=%i)\n",
                                                               ~^
                                                               %lx
   In file included from include/linux/kernel.h:14:0,
                    from include/linux/list.h:9,
                    from include/linux/preempt.h:11,
                    from include/linux/spinlock.h:51,
                    from include/linux/fdtable.h:11,
                    from fs/notify/fanotify/fanotify.c:3:
   include/linux/kern_levels.h:5:18: warning: format '%x' expects argument of type 'unsigned int', but argument 3 has type 'long int' [-Wformat=]
    #define KERN_SOH "\001"  /* ASCII Start Of Header */
                     ^
   include/linux/printk.h:424:10: note: in definition of macro 'printk_ratelimited'
      printk(fmt, ##__VA_ARGS__);    \
             ^~~
   include/linux/kern_levels.h:12:22: note: in expansion of macro 'KERN_SOH'
    #define KERN_WARNING KERN_SOH "4" /* warning conditions */
                         ^~~~~~~~
   include/linux/printk.h:440:21: note: in expansion of macro 'KERN_WARNING'
     printk_ratelimited(KERN_WARNING pr_fmt(fmt), ##__VA_ARGS__)
                        ^~~~~~~~~~~~
>> fs/notify/fanotify/fanotify.c:196:2: note: in expansion of macro 'pr_warn_ratelimited'
     pr_warn_ratelimited("fanotify: failed to encode fid (fsid=%x.%x, type=%d, bytes=%d, err=%i)\n",
     ^~~~~~~~~~~~~~~~~~~
   fs/notify/fanotify/fanotify.c:196:64: note: format string is defined here
     pr_warn_ratelimited("fanotify: failed to encode fid (fsid=%x.%x, type=%d, bytes=%d, err=%i)\n",
                                                                  ~^
                                                                  %lx

vim +/pr_warn_ratelimited +196 fs/notify/fanotify/fanotify.c

   154	
   155	static int fanotify_encode_fid(struct fanotify_event *event,
   156				       const struct path *path, gfp_t gfp)
   157	{
   158		struct fanotify_fid *fid = &event->fid;
   159		int dwords, bytes = 0;
   160		struct kstatfs stat;
   161		int err, type;
   162	
   163		stat.f_fsid.val[0] = stat.f_fsid.val[1] = 0;
   164		fid->ext_fh = NULL;
   165		dwords = 0;
   166		err = -ENOENT;
   167		type = exportfs_encode_fh(path->dentry, NULL, &dwords,  0);
   168		if (!dwords)
   169			goto out_err;
   170	
   171		err = vfs_statfs(path, &stat);
   172		if (err)
   173			goto out_err;
   174	
   175		bytes = dwords << 2;
   176		if (bytes > FANOTIFY_INLINE_FH_LEN) {
   177			/* Treat failure to allocate fh as failure to allocate event */
   178			err = -ENOMEM;
   179			fid->ext_fh = kmalloc(bytes, gfp);
   180			if (!fid->ext_fh)
   181				goto out_err;
   182		}
   183	
   184		type = exportfs_encode_fh(path->dentry, fanotify_fid_fh(fid, bytes),
   185					  &dwords,  0);
   186		err = -EINVAL;
   187		if (!type || type == FILEID_INVALID || bytes != dwords << 2)
   188			goto out_err;
   189	
   190		fid->fsid = stat.f_fsid;
   191		event->fh_len = bytes;
   192	
   193		return type;
   194	
   195	out_err:
 > 196		pr_warn_ratelimited("fanotify: failed to encode fid (fsid=%x.%x, type=%d, bytes=%d, err=%i)\n",
   197				    stat.f_fsid.val[0], stat.f_fsid.val[1],
   198				    type, bytes, err);
   199		kfree(fid->ext_fh);
   200		fid->ext_fh = NULL;
   201		event->fh_len = 0;
   202	
   203		return FILEID_INVALID;
   204	}
   205	

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 58686 bytes --]

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH v5 07/17] fanotify: encode file identifier for FAN_REPORT_FID
  2019-01-11  8:10   ` kbuild test robot
@ 2019-01-11  8:37     ` Amir Goldstein
  2019-01-18 18:39       ` Paul Burton
  0 siblings, 1 reply; 34+ messages in thread
From: Amir Goldstein @ 2019-01-11  8:37 UTC (permalink / raw)
  To: Ralf Baechle
  Cc: kbuild-all, Jan Kara, Matthew Bobrowski, linux-fsdevel, linux-mips

On Fri, Jan 11, 2019 at 10:11 AM kbuild test robot <lkp@intel.com> wrote:
>
> Hi Amir,
>
> I love your patch! Perhaps something to improve:
>
> [auto build test WARNING on linus/master]
> [also build test WARNING on v5.0-rc1]
> [if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
>
> url:    https://github.com/0day-ci/linux/commits/Amir-Goldstein/fanotify-add-support-for-more-event-types/20190111-090241
> config: mips-allmodconfig (attached as .config)
> compiler: mips-linux-gnu-gcc (Debian 7.2.0-11) 7.2.0
> reproduce:
>         wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
>         chmod +x ~/bin/make.cross
>         # save the attached .config to linux build tree
>         GCC_VERSION=7.2.0 make.cross ARCH=mips
>
> All warnings (new ones prefixed by >>):
>
>    In file included from include/linux/kernel.h:14:0,
>                     from include/linux/list.h:9,
>                     from include/linux/preempt.h:11,
>                     from include/linux/spinlock.h:51,
>                     from include/linux/fdtable.h:11,
>                     from fs/notify/fanotify/fanotify.c:3:
>    fs/notify/fanotify/fanotify.c: In function 'fanotify_encode_fid':
>    include/linux/kern_levels.h:5:18: warning: format '%x' expects argument of type 'unsigned int', but argument 2 has type 'long int' [-Wformat=]

I'm confused.
__kernel_fsid_t val member is long[] on mips arch and int[] on other archs.
Which format specifier am I supposed to use to print it?

Thanks,
Amir.

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH v5 10/17] fanotify: cache fsid in fsnotify_mark_connector
  2019-01-10 17:04 ` [PATCH v5 10/17] fanotify: cache fsid in fsnotify_mark_connector Amir Goldstein
  2019-01-11  3:13   ` kbuild test robot
@ 2019-01-14  7:30   ` Dan Carpenter
  2019-01-14  7:30     ` Dan Carpenter
  2019-01-14  9:17     ` Amir Goldstein
  2019-02-07 14:48   ` Jan Kara
  2 siblings, 2 replies; 34+ messages in thread
From: Dan Carpenter @ 2019-01-14  7:30 UTC (permalink / raw)
  To: kbuild, Amir Goldstein
  Cc: linux-fsdevel, Matthew Bobrowski, Jan Kara, kbuild-all

Hi Amir,

url:    https://github.com/0day-ci/linux/commits/Amir-Goldstein/fanotify-add-support-for-more-event-types/20190111-090241

smatch warnings:
fs/notify/fanotify/fanotify.c:194 fanotify_encode_fid() error: uninitialized symbol 'type'.
fs/notify/fanotify/fanotify.c:194 fanotify_encode_fid() error: uninitialized symbol 'err'.

# https://github.com/0day-ci/linux/commit/48b7a1af51abcb893917d986bc5ae5bae2d21ad6
git remote add linux-review https://github.com/0day-ci/linux
git remote update linux-review
git checkout 48b7a1af51abcb893917d986bc5ae5bae2d21ad6
vim +/type +194 fs/notify/fanotify/fanotify.c

1c529063 Eric Paris     2009-12-17  154  
688d9244 Amir Goldstein 2019-01-10  155  static int fanotify_encode_fid(struct fanotify_event *event,
48b7a1af Amir Goldstein 2019-01-10  156  			       const struct path *path, gfp_t gfp,
48b7a1af Amir Goldstein 2019-01-10  157  			       __kernel_fsid_t *fsid)
688d9244 Amir Goldstein 2019-01-10  158  {
688d9244 Amir Goldstein 2019-01-10  159  	struct fanotify_fid *fid = &event->fid;
688d9244 Amir Goldstein 2019-01-10  160  	int dwords, bytes = 0;
688d9244 Amir Goldstein 2019-01-10  161  	int err, type;
688d9244 Amir Goldstein 2019-01-10  162  
48b7a1af Amir Goldstein 2019-01-10  163  	if (!fsid)
48b7a1af Amir Goldstein 2019-01-10  164  		goto out_err;
48b7a1af Amir Goldstein 2019-01-10  165  
688d9244 Amir Goldstein 2019-01-10  166  	fid->ext_fh = NULL;
688d9244 Amir Goldstein 2019-01-10  167  	dwords = 0;
688d9244 Amir Goldstein 2019-01-10  168  	err = -ENOENT;
688d9244 Amir Goldstein 2019-01-10  169  	type = exportfs_encode_fh(path->dentry, NULL, &dwords,  0);
688d9244 Amir Goldstein 2019-01-10  170  	if (!dwords)
688d9244 Amir Goldstein 2019-01-10  171  		goto out_err;
688d9244 Amir Goldstein 2019-01-10  172  
688d9244 Amir Goldstein 2019-01-10  173  	bytes = dwords << 2;
688d9244 Amir Goldstein 2019-01-10  174  	if (bytes > FANOTIFY_INLINE_FH_LEN) {
688d9244 Amir Goldstein 2019-01-10  175  		/* Treat failure to allocate fh as failure to allocate event */
688d9244 Amir Goldstein 2019-01-10  176  		err = -ENOMEM;
688d9244 Amir Goldstein 2019-01-10  177  		fid->ext_fh = kmalloc(bytes, gfp);
688d9244 Amir Goldstein 2019-01-10  178  		if (!fid->ext_fh)
688d9244 Amir Goldstein 2019-01-10  179  			goto out_err;
688d9244 Amir Goldstein 2019-01-10  180  	}
688d9244 Amir Goldstein 2019-01-10  181  
688d9244 Amir Goldstein 2019-01-10  182  	type = exportfs_encode_fh(path->dentry, fanotify_fid_fh(fid, bytes),
688d9244 Amir Goldstein 2019-01-10  183  				  &dwords,  0);
688d9244 Amir Goldstein 2019-01-10  184  	err = -EINVAL;
688d9244 Amir Goldstein 2019-01-10  185  	if (!type || type == FILEID_INVALID || bytes != dwords << 2)
688d9244 Amir Goldstein 2019-01-10  186  		goto out_err;
688d9244 Amir Goldstein 2019-01-10  187  
48b7a1af Amir Goldstein 2019-01-10  188  	fid->fsid = *fsid;
688d9244 Amir Goldstein 2019-01-10  189  	event->fh_len = bytes;
688d9244 Amir Goldstein 2019-01-10  190  
688d9244 Amir Goldstein 2019-01-10  191  	return type;
688d9244 Amir Goldstein 2019-01-10  192  
688d9244 Amir Goldstein 2019-01-10  193  out_err:
688d9244 Amir Goldstein 2019-01-10 @194  	pr_warn_ratelimited("fanotify: failed to encode fid (fsid=%x.%x, type=%d, bytes=%d, err=%i)\n",
48b7a1af Amir Goldstein 2019-01-10  195  			    fsid ? fsid->val[0] : 0, fsid ? fsid->val[1] : 0,
688d9244 Amir Goldstein 2019-01-10  196  			    type, bytes, err);
688d9244 Amir Goldstein 2019-01-10  197  	kfree(fid->ext_fh);
688d9244 Amir Goldstein 2019-01-10  198  	fid->ext_fh = NULL;
688d9244 Amir Goldstein 2019-01-10  199  	event->fh_len = 0;
688d9244 Amir Goldstein 2019-01-10  200  
688d9244 Amir Goldstein 2019-01-10  201  	return FILEID_INVALID;
688d9244 Amir Goldstein 2019-01-10  202  }
688d9244 Amir Goldstein 2019-01-10  203  

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH v5 10/17] fanotify: cache fsid in fsnotify_mark_connector
  2019-01-14  7:30   ` Dan Carpenter
@ 2019-01-14  7:30     ` Dan Carpenter
  2019-01-14  9:17     ` Amir Goldstein
  1 sibling, 0 replies; 34+ messages in thread
From: Dan Carpenter @ 2019-01-14  7:30 UTC (permalink / raw)
  To: kbuild, Amir Goldstein
  Cc: kbuild-all, Jan Kara, Matthew Bobrowski, linux-fsdevel

Hi Amir,

url:    https://github.com/0day-ci/linux/commits/Amir-Goldstein/fanotify-add-support-for-more-event-types/20190111-090241

smatch warnings:
fs/notify/fanotify/fanotify.c:194 fanotify_encode_fid() error: uninitialized symbol 'type'.
fs/notify/fanotify/fanotify.c:194 fanotify_encode_fid() error: uninitialized symbol 'err'.

# https://github.com/0day-ci/linux/commit/48b7a1af51abcb893917d986bc5ae5bae2d21ad6
git remote add linux-review https://github.com/0day-ci/linux
git remote update linux-review
git checkout 48b7a1af51abcb893917d986bc5ae5bae2d21ad6
vim +/type +194 fs/notify/fanotify/fanotify.c

1c529063 Eric Paris     2009-12-17  154  
688d9244 Amir Goldstein 2019-01-10  155  static int fanotify_encode_fid(struct fanotify_event *event,
48b7a1af Amir Goldstein 2019-01-10  156  			       const struct path *path, gfp_t gfp,
48b7a1af Amir Goldstein 2019-01-10  157  			       __kernel_fsid_t *fsid)
688d9244 Amir Goldstein 2019-01-10  158  {
688d9244 Amir Goldstein 2019-01-10  159  	struct fanotify_fid *fid = &event->fid;
688d9244 Amir Goldstein 2019-01-10  160  	int dwords, bytes = 0;
688d9244 Amir Goldstein 2019-01-10  161  	int err, type;
688d9244 Amir Goldstein 2019-01-10  162  
48b7a1af Amir Goldstein 2019-01-10  163  	if (!fsid)
48b7a1af Amir Goldstein 2019-01-10  164  		goto out_err;
48b7a1af Amir Goldstein 2019-01-10  165  
688d9244 Amir Goldstein 2019-01-10  166  	fid->ext_fh = NULL;
688d9244 Amir Goldstein 2019-01-10  167  	dwords = 0;
688d9244 Amir Goldstein 2019-01-10  168  	err = -ENOENT;
688d9244 Amir Goldstein 2019-01-10  169  	type = exportfs_encode_fh(path->dentry, NULL, &dwords,  0);
688d9244 Amir Goldstein 2019-01-10  170  	if (!dwords)
688d9244 Amir Goldstein 2019-01-10  171  		goto out_err;
688d9244 Amir Goldstein 2019-01-10  172  
688d9244 Amir Goldstein 2019-01-10  173  	bytes = dwords << 2;
688d9244 Amir Goldstein 2019-01-10  174  	if (bytes > FANOTIFY_INLINE_FH_LEN) {
688d9244 Amir Goldstein 2019-01-10  175  		/* Treat failure to allocate fh as failure to allocate event */
688d9244 Amir Goldstein 2019-01-10  176  		err = -ENOMEM;
688d9244 Amir Goldstein 2019-01-10  177  		fid->ext_fh = kmalloc(bytes, gfp);
688d9244 Amir Goldstein 2019-01-10  178  		if (!fid->ext_fh)
688d9244 Amir Goldstein 2019-01-10  179  			goto out_err;
688d9244 Amir Goldstein 2019-01-10  180  	}
688d9244 Amir Goldstein 2019-01-10  181  
688d9244 Amir Goldstein 2019-01-10  182  	type = exportfs_encode_fh(path->dentry, fanotify_fid_fh(fid, bytes),
688d9244 Amir Goldstein 2019-01-10  183  				  &dwords,  0);
688d9244 Amir Goldstein 2019-01-10  184  	err = -EINVAL;
688d9244 Amir Goldstein 2019-01-10  185  	if (!type || type == FILEID_INVALID || bytes != dwords << 2)
688d9244 Amir Goldstein 2019-01-10  186  		goto out_err;
688d9244 Amir Goldstein 2019-01-10  187  
48b7a1af Amir Goldstein 2019-01-10  188  	fid->fsid = *fsid;
688d9244 Amir Goldstein 2019-01-10  189  	event->fh_len = bytes;
688d9244 Amir Goldstein 2019-01-10  190  
688d9244 Amir Goldstein 2019-01-10  191  	return type;
688d9244 Amir Goldstein 2019-01-10  192  
688d9244 Amir Goldstein 2019-01-10  193  out_err:
688d9244 Amir Goldstein 2019-01-10 @194  	pr_warn_ratelimited("fanotify: failed to encode fid (fsid=%x.%x, type=%d, bytes=%d, err=%i)\n",
48b7a1af Amir Goldstein 2019-01-10  195  			    fsid ? fsid->val[0] : 0, fsid ? fsid->val[1] : 0,
688d9244 Amir Goldstein 2019-01-10  196  			    type, bytes, err);
688d9244 Amir Goldstein 2019-01-10  197  	kfree(fid->ext_fh);
688d9244 Amir Goldstein 2019-01-10  198  	fid->ext_fh = NULL;
688d9244 Amir Goldstein 2019-01-10  199  	event->fh_len = 0;
688d9244 Amir Goldstein 2019-01-10  200  
688d9244 Amir Goldstein 2019-01-10  201  	return FILEID_INVALID;
688d9244 Amir Goldstein 2019-01-10  202  }
688d9244 Amir Goldstein 2019-01-10  203  

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH v5 10/17] fanotify: cache fsid in fsnotify_mark_connector
  2019-01-14  7:30   ` Dan Carpenter
  2019-01-14  7:30     ` Dan Carpenter
@ 2019-01-14  9:17     ` Amir Goldstein
  1 sibling, 0 replies; 34+ messages in thread
From: Amir Goldstein @ 2019-01-14  9:17 UTC (permalink / raw)
  To: Dan Carpenter
  Cc: kbuild, kbuild-all, Jan Kara, Matthew Bobrowski, linux-fsdevel

On Mon, Jan 14, 2019 at 9:31 AM Dan Carpenter <dan.carpenter@oracle.com> wrote:
>
> Hi Amir,
>
> url:    https://github.com/0day-ci/linux/commits/Amir-Goldstein/fanotify-add-support-for-more-event-types/20190111-090241
>
> smatch warnings:
> fs/notify/fanotify/fanotify.c:194 fanotify_encode_fid() error: uninitialized symbol 'type'.
> fs/notify/fanotify/fanotify.c:194 fanotify_encode_fid() error: uninitialized symbol 'err'.
>
> # https://github.com/0day-ci/linux/commit/48b7a1af51abcb893917d986bc5ae5bae2d21ad6
> git remote add linux-review https://github.com/0day-ci/linux
> git remote update linux-review
> git checkout 48b7a1af51abcb893917d986bc5ae5bae2d21ad6
> vim +/type +194 fs/notify/fanotify/fanotify.c
>

Thanks for the report!

> 1c529063 Eric Paris     2009-12-17  154
> 688d9244 Amir Goldstein 2019-01-10  155  static int fanotify_encode_fid(struct fanotify_event *event,
> 48b7a1af Amir Goldstein 2019-01-10  156                                const struct path *path, gfp_t gfp,
> 48b7a1af Amir Goldstein 2019-01-10  157                                __kernel_fsid_t *fsid)
> 688d9244 Amir Goldstein 2019-01-10  158  {
> 688d9244 Amir Goldstein 2019-01-10  159         struct fanotify_fid *fid = &event->fid;
> 688d9244 Amir Goldstein 2019-01-10  160         int dwords, bytes = 0;
> 688d9244 Amir Goldstein 2019-01-10  161         int err, type;
> 688d9244 Amir Goldstein 2019-01-10  162
> 48b7a1af Amir Goldstein 2019-01-10  163         if (!fsid)
> 48b7a1af Amir Goldstein 2019-01-10  164                 goto out_err;


Jan,

Can you fix this up on commit to:
int err = -ENODEV;
int type = FILEID_INVALID;

Thanks,
Amir.

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH v5 07/17] fanotify: encode file identifier for FAN_REPORT_FID
  2019-01-11  8:37     ` Amir Goldstein
@ 2019-01-18 18:39       ` Paul Burton
  0 siblings, 0 replies; 34+ messages in thread
From: Paul Burton @ 2019-01-18 18:39 UTC (permalink / raw)
  To: Amir Goldstein
  Cc: Ralf Baechle, kbuild-all, Jan Kara, Matthew Bobrowski,
	linux-fsdevel, linux-mips, Arnd Bergmann, linux-arch

Hi Amir,

On Fri, Jan 11, 2019 at 10:37:39AM +0200, Amir Goldstein wrote:
> On Fri, Jan 11, 2019 at 10:11 AM kbuild test robot <lkp@intel.com> wrote:
> >
> > Hi Amir,
> >
> > I love your patch! Perhaps something to improve:
> >
> > [auto build test WARNING on linus/master]
> > [also build test WARNING on v5.0-rc1]
> > [if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
> >
> > url:    https://github.com/0day-ci/linux/commits/Amir-Goldstein/fanotify-add-support-for-more-event-types/20190111-090241
> > config: mips-allmodconfig (attached as .config)
> > compiler: mips-linux-gnu-gcc (Debian 7.2.0-11) 7.2.0
> > reproduce:
> >         wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
> >         chmod +x ~/bin/make.cross
> >         # save the attached .config to linux build tree
> >         GCC_VERSION=7.2.0 make.cross ARCH=mips
> >
> > All warnings (new ones prefixed by >>):
> >
> >    In file included from include/linux/kernel.h:14:0,
> >                     from include/linux/list.h:9,
> >                     from include/linux/preempt.h:11,
> >                     from include/linux/spinlock.h:51,
> >                     from include/linux/fdtable.h:11,
> >                     from fs/notify/fanotify/fanotify.c:3:
> >    fs/notify/fanotify/fanotify.c: In function 'fanotify_encode_fid':
> >    include/linux/kern_levels.h:5:18: warning: format '%x' expects argument of type 'unsigned int', but argument 2 has type 'long int' [-Wformat=]
> 
> I'm confused.
> __kernel_fsid_t val member is long[] on mips arch and int[] on other archs.
> Which format specifier am I supposed to use to print it?

That's a good question.

Here's another: why on Earth do we have this custom __kernel_fsid_t
definition for MIPS at all..?

We only provide the MIPS definition when _MIPS_SZLONG == 32, ie. when
long is the same size as int & the generic definition of the struct
would have an identical memory layout anyway.

So I'm tempted to just delete this weird code - the only thing that
might break is if someone is doing something that really expects a long
& cares about getting an int of the same size. For example if anyone
prints the value with %lx or the like - essentially the opposite case to
yours.

I consider it pretty unlikely that anyone will be doing this in a
MIPS32-specific codepath such that they've been seeing the custom
__kernel_fsid_t up until now, but does anyone see a problem with this?

Thanks,
    Paul

---
diff --git a/arch/mips/include/uapi/asm/posix_types.h b/arch/mips/include/uapi/asm/posix_types.h
index 6aa49c10f88f..f0ccb5b90ce9 100644
--- a/arch/mips/include/uapi/asm/posix_types.h
+++ b/arch/mips/include/uapi/asm/posix_types.h
@@ -21,13 +21,6 @@
 typedef long		__kernel_daddr_t;
 #define __kernel_daddr_t __kernel_daddr_t

-#if (_MIPS_SZLONG == 32)
-typedef struct {
-	long	val[2];
-} __kernel_fsid_t;
-#define __kernel_fsid_t __kernel_fsid_t
-#endif
-
 #include <asm-generic/posix_types.h>

 #endif /* _ASM_POSIX_TYPES_H */

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH v5 01/17] fsnotify: annotate directory entry modification events
  2019-01-10 17:04 ` [PATCH v5 01/17] fsnotify: annotate directory entry modification events Amir Goldstein
@ 2019-02-06 14:14   ` Jan Kara
  0 siblings, 0 replies; 34+ messages in thread
From: Jan Kara @ 2019-02-06 14:14 UTC (permalink / raw)
  To: Amir Goldstein; +Cc: Jan Kara, Matthew Bobrowski, linux-fsdevel

On Thu 10-01-19 19:04:28, Amir Goldstein wrote:
> "dirent" events are referring to events that modify directory entries,
> such as create,delete,rename. Those events should always be reported
> on a watched directory, regardless if FS_EVENT_ON_CHILD is set
> on the watch mask.
> 
> fsnotify_nameremove() and fsnotify_move() were modified to no longer
> set the FS_EVENT_ON_CHILD event bit. This is a semantic change to
> align with the "dirent" event definition. It has no effect on any
> existing backend, because dnotify, inotify and audit always requets the
> child events and fanotify does not get the delete,rename events.
> 
> The fsnotify_dirent() helper is used instead of fsnotify_parent() to
> report a dirent event to dentry->d_parent without FS_EVENT_ON_CHILD
> and regardless if parent has the FS_EVENT_ON_CHILD bit set.
> 
> Unlike fsnotify_parent(), fsnotify_dirent() assumes that dentry->d_name
> and dentry->d_parent are stable. For fsnotify_create()/fsnotify_mkdir(),
> this assumption is abviously correct. For fsnotify_nameremove(), it is
> less trvial, so we use dget_parent() and take_dentry_name_snapshot() to
> grab stable references.
> 
> Signed-off-by: Amir Goldstein <amir73il@gmail.com>

I've taken the liberty of removing the case analysis from
fsnotify_nameremove() comment. That is bound to become out of date pretty
soon and not very useful for the reader. Otherwise the patch looks good and
I've added it to my tree.

								Honza

> ---
>  include/linux/fsnotify.h | 68 ++++++++++++++++++++++++++++++++++------
>  1 file changed, 59 insertions(+), 9 deletions(-)
> 
> diff --git a/include/linux/fsnotify.h b/include/linux/fsnotify.h
> index 2ccb08cb5d6a..116907928c7f 100644
> --- a/include/linux/fsnotify.h
> +++ b/include/linux/fsnotify.h
> @@ -17,8 +17,22 @@
>  #include <linux/slab.h>
>  #include <linux/bug.h>
>  
> +/*
> + * Notify this @dir inode about a change in the directory entry @dentry.
> + *
> + * Unlike fsnotify_parent(), the event will be reported regardless of the
> + * FS_EVENT_ON_CHILD mask on the parent inode.
> + */
> +static inline int fsnotify_dirent(struct inode *dir, struct dentry *dentry,
> +				  __u32 mask)
> +{
> +	return fsnotify(dir, mask, d_inode(dentry), FSNOTIFY_EVENT_INODE,
> +			dentry->d_name.name, 0);
> +}
> +
>  /* Notify this dentry's parent about a child's events. */
> -static inline int fsnotify_parent(const struct path *path, struct dentry *dentry, __u32 mask)
> +static inline int fsnotify_parent(const struct path *path,
> +				  struct dentry *dentry, __u32 mask)
>  {
>  	if (!dentry)
>  		dentry = path->dentry;
> @@ -85,8 +99,8 @@ static inline void fsnotify_move(struct inode *old_dir, struct inode *new_dir,
>  {
>  	struct inode *source = moved->d_inode;
>  	u32 fs_cookie = fsnotify_get_cookie();
> -	__u32 old_dir_mask = (FS_EVENT_ON_CHILD | FS_MOVED_FROM);
> -	__u32 new_dir_mask = (FS_EVENT_ON_CHILD | FS_MOVED_TO);
> +	__u32 old_dir_mask = FS_MOVED_FROM;
> +	__u32 new_dir_mask = FS_MOVED_TO;
>  	const unsigned char *new_name = moved->d_name.name;
>  
>  	if (old_dir == new_dir)
> @@ -128,15 +142,54 @@ static inline void fsnotify_vfsmount_delete(struct vfsmount *mnt)
>  
>  /*
>   * fsnotify_nameremove - a filename was removed from a directory
> + *
> + * Called from d_delete() and nfs_complete_sillyrename().
> + * The latter is called from nfs client ->unlink() ->rmdir() ->rename()
> + * under parent vfs inode lock.
> + *
> + * Most filesystems call d_delete() from ->unlink() ->rmdir() ->rename()
> + * ops under parent vfs inode lock.
> + *
> + * Some pseudo filesystems call d_delete() without parent inode lock.
> + * Those filesystems have no ->rename() op and they do not call
> + * d_move() directly, so d_parent and d_name are stable by definition.
> + * Examples: devpts, efivarfs, rpc_pipefs, functionfs.
> + *
> + * Some clustered filesystems call d_delete() on remote nodes, not under
> + * vfs parent inode lock, but they use cluster distributed locks on local
> + * and remote nodes. Those filesystems call d_delete() under their cluster
> + * lock. Examples:
> + * - in ceph_fill_trace() under CEPH_MDS_R_PARENT_LOCKED
> + * - in ocfs2_dentry_convert_worker() under ocfs2_dentry_lock
> + * But those filesystems also call d_move() under the same cluster lock
> + * (i.e. FS_RENAME_DOES_D_MOVE), so d_parent and d_name are also stable.
> + *
> + * However, to be on the safe side and be reselient to future callers
> + * and out of tree users of d_delete(), we do not assume that d_parent and
> + * d_name are stable and we use dget_parent() and take_dentry_name_snapshot()
> + * to grab stable references.
>   */
>  static inline void fsnotify_nameremove(struct dentry *dentry, int isdir)
>  {
> +	struct dentry *parent;
> +	struct name_snapshot name;
>  	__u32 mask = FS_DELETE;
>  
> +	/* d_delete() of pseudo inode? (e.g. __ns_get_path() playing tricks) */
> +	if (IS_ROOT(dentry))
> +		return;
> +
>  	if (isdir)
>  		mask |= FS_ISDIR;
>  
> -	fsnotify_parent(NULL, dentry, mask);
> +	parent = dget_parent(dentry);
> +	take_dentry_name_snapshot(&name, dentry);
> +
> +	fsnotify(d_inode(parent), mask, d_inode(dentry), FSNOTIFY_EVENT_INODE,
> +		 name.name, 0);
> +
> +	release_dentry_name_snapshot(&name);
> +	dput(parent);
>  }
>  
>  /*
> @@ -155,7 +208,7 @@ static inline void fsnotify_create(struct inode *inode, struct dentry *dentry)
>  {
>  	audit_inode_child(inode, dentry, AUDIT_TYPE_CHILD_CREATE);
>  
> -	fsnotify(inode, FS_CREATE, dentry->d_inode, FSNOTIFY_EVENT_INODE, dentry->d_name.name, 0);
> +	fsnotify_dirent(inode, dentry, FS_CREATE);
>  }
>  
>  /*
> @@ -176,12 +229,9 @@ static inline void fsnotify_link(struct inode *dir, struct inode *inode, struct
>   */
>  static inline void fsnotify_mkdir(struct inode *inode, struct dentry *dentry)
>  {
> -	__u32 mask = (FS_CREATE | FS_ISDIR);
> -	struct inode *d_inode = dentry->d_inode;
> -
>  	audit_inode_child(inode, dentry, AUDIT_TYPE_CHILD_CREATE);
>  
> -	fsnotify(inode, mask, d_inode, FSNOTIFY_EVENT_INODE, dentry->d_name.name, 0);
> +	fsnotify_dirent(inode, dentry, FS_CREATE | FS_ISDIR);
>  }
>  
>  /*
> -- 
> 2.17.1
> 
-- 
Jan Kara <jack@suse.com>
SUSE Labs, CR

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH v5 08/17] fanotify: copy event fid info to user
  2019-01-10 17:04 ` [PATCH v5 08/17] fanotify: copy event fid info to user Amir Goldstein
@ 2019-02-06 17:41   ` Jan Kara
  0 siblings, 0 replies; 34+ messages in thread
From: Jan Kara @ 2019-02-06 17:41 UTC (permalink / raw)
  To: Amir Goldstein; +Cc: Jan Kara, Matthew Bobrowski, linux-fsdevel, linux-api

On Thu 10-01-19 19:04:35, Amir Goldstein wrote:
> If group requested FAN_REPORT_FID and event has file identifier,
> copy that information to user reading the event after event metadata.
> 
> fid information is formatted as struct fanotify_event_info_fid
> that includes a generic header struct fanotify_event_info_header,
> so that other info types could be defined in the future using the
> same header.
> 
> metadata->event_len includes the length of the fid information.
> 
> The fid information includes the filesystem's fsid (see statfs(2))
> followed by an NFS file handle of the file that could be passed as
> an argument to open_by_handle_at(2).
> 
> Cc: <linux-api@vger.kernel.org>
> Signed-off-by: Amir Goldstein <amir73il@gmail.com>

> +#define FANOTIFY_EVENT_ALIGN (sizeof(struct fanotify_event_info_header))

Here I did a small change of setting FANOTIFY_EVENT_ALIGN to plain 4. It
just seems more logical to me to have the alignment specified as an
absolute number rather than a size of some structure...

								Honza
-- 
Jan Kara <jack@suse.com>
SUSE Labs, CR

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH v5 10/17] fanotify: cache fsid in fsnotify_mark_connector
  2019-01-10 17:04 ` [PATCH v5 10/17] fanotify: cache fsid in fsnotify_mark_connector Amir Goldstein
  2019-01-11  3:13   ` kbuild test robot
  2019-01-14  7:30   ` Dan Carpenter
@ 2019-02-07 14:48   ` Jan Kara
  2019-02-07 16:31     ` Amir Goldstein
  2 siblings, 1 reply; 34+ messages in thread
From: Jan Kara @ 2019-02-07 14:48 UTC (permalink / raw)
  To: Amir Goldstein; +Cc: Jan Kara, Matthew Bobrowski, linux-fsdevel

[-- Attachment #1: Type: text/plain, Size: 20062 bytes --]

On Thu 10-01-19 19:04:37, Amir Goldstein wrote:
> For FAN_REPORT_FID, we need to encode fid with fsid of the filesystem on
> every event. To avoid having to call vfs_statfs() on every event to get
> fsid, we store the fsid in fsnotify_mark_connector on the first time we
> add a mark and on handle event we use the cached fsid.
> 
> Subsequent calls to add mark on the same object are expected to pass the
> same fsid, so the call will fail on cached fsid mismatch.
> 
> If an event is reported on several mark types (inode, mount, filesystem),
> all connectors should already have the same fsid, so we use the cached
> fsid from the first connector.
> 
> Suggested-by: Jan Kara <jack@suse.cz>
> Signed-off-by: Amir Goldstein <amir73il@gmail.com>

I've somewhat modified the patch to simplify code flow around
fanotify_get_fid() and also made fsid argument for
fsnotify_add_mark_locked() mandatory. The resulting patch is attached.

								Honza

> ---
>  fs/notify/fanotify/fanotify.c      | 51 +++++++++++++++++-------
>  fs/notify/fanotify/fanotify.h      |  5 ++-
>  fs/notify/fanotify/fanotify_user.c | 62 ++++++++++++++++++------------
>  fs/notify/mark.c                   | 47 +++++++++++++++++-----
>  include/linux/fsnotify_backend.h   | 24 +++++++++---
>  5 files changed, 135 insertions(+), 54 deletions(-)
> 
> diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c
> index e431f63c9f58..1bbf8b90dd83 100644
> --- a/fs/notify/fanotify/fanotify.c
> +++ b/fs/notify/fanotify/fanotify.c
> @@ -153,14 +153,16 @@ static u32 fanotify_group_event_mask(struct fsnotify_iter_info *iter_info,
>  }
>  
>  static int fanotify_encode_fid(struct fanotify_event *event,
> -			       const struct path *path, gfp_t gfp)
> +			       const struct path *path, gfp_t gfp,
> +			       __kernel_fsid_t *fsid)
>  {
>  	struct fanotify_fid *fid = &event->fid;
>  	int dwords, bytes = 0;
> -	struct kstatfs stat;
>  	int err, type;
>  
> -	stat.f_fsid.val[0] = stat.f_fsid.val[1] = 0;
> +	if (!fsid)
> +		goto out_err;
> +
>  	fid->ext_fh = NULL;
>  	dwords = 0;
>  	err = -ENOENT;
> @@ -168,10 +170,6 @@ static int fanotify_encode_fid(struct fanotify_event *event,
>  	if (!dwords)
>  		goto out_err;
>  
> -	err = vfs_statfs(path, &stat);
> -	if (err)
> -		goto out_err;
> -
>  	bytes = dwords << 2;
>  	if (bytes > FANOTIFY_INLINE_FH_LEN) {
>  		/* Treat failure to allocate fh as failure to allocate event */
> @@ -187,14 +185,14 @@ static int fanotify_encode_fid(struct fanotify_event *event,
>  	if (!type || type == FILEID_INVALID || bytes != dwords << 2)
>  		goto out_err;
>  
> -	fid->fsid = stat.f_fsid;
> +	fid->fsid = *fsid;
>  	event->fh_len = bytes;
>  
>  	return type;
>  
>  out_err:
>  	pr_warn_ratelimited("fanotify: failed to encode fid (fsid=%x.%x, type=%d, bytes=%d, err=%i)\n",
> -			    stat.f_fsid.val[0], stat.f_fsid.val[1],
> +			    fsid ? fsid->val[0] : 0, fsid ? fsid->val[1] : 0,
>  			    type, bytes, err);
>  	kfree(fid->ext_fh);
>  	fid->ext_fh = NULL;
> @@ -204,8 +202,9 @@ static int fanotify_encode_fid(struct fanotify_event *event,
>  }
>  
>  struct fanotify_event *fanotify_alloc_event(struct fsnotify_group *group,
> -						 struct inode *inode, u32 mask,
> -						 const struct path *path)
> +					    struct inode *inode, u32 mask,
> +					    const struct path *path,
> +					    __kernel_fsid_t *fsid)
>  {
>  	struct fanotify_event *event = NULL;
>  	gfp_t gfp = GFP_KERNEL_ACCOUNT;
> @@ -244,7 +243,7 @@ init: __maybe_unused
>  	event->fh_len = 0;
>  	if (path && FAN_GROUP_FLAG(group, FAN_REPORT_FID)) {
>  		/* Report the event without a file identifier on encode error */
> -		event->fh_type = fanotify_encode_fid(event, path, gfp);
> +		event->fh_type = fanotify_encode_fid(event, path, gfp, fsid);
>  	} else if (path) {
>  		event->fh_type = FILEID_ROOT;
>  		event->path = *path;
> @@ -259,6 +258,28 @@ init: __maybe_unused
>  	return event;
>  }
>  
> +/*
> + * Get cached fsid of the filesystem containing the object from any connector.
> + * All connectors are supposed to have the same fsid, but we do not verify that
> + * here.
> + */
> +static __kernel_fsid_t *fanotify_get_fsid(struct fsnotify_iter_info *iter_info,
> +					  __kernel_fsid_t *fsid)
> +{
> +	int type;
> +
> +	fsnotify_foreach_obj_type(type) {
> +		if (!fsnotify_iter_should_report_type(iter_info, type))
> +			continue;
> +
> +		*fsid = iter_info->marks[type]->connector->fsid;
> +		if (!WARN_ON_ONCE(!fsid->val[0] && !fsid->val[1]))
> +			return fsid;
> +	}
> +
> +	return NULL;
> +}
> +
>  static int fanotify_handle_event(struct fsnotify_group *group,
>  				 struct inode *inode,
>  				 u32 mask, const void *data, int data_type,
> @@ -268,6 +289,7 @@ static int fanotify_handle_event(struct fsnotify_group *group,
>  	int ret = 0;
>  	struct fanotify_event *event;
>  	struct fsnotify_event *fsn_event;
> +	__kernel_fsid_t __fsid, *fsid = NULL;
>  
>  	BUILD_BUG_ON(FAN_ACCESS != FS_ACCESS);
>  	BUILD_BUG_ON(FAN_MODIFY != FS_MODIFY);
> @@ -300,7 +322,10 @@ static int fanotify_handle_event(struct fsnotify_group *group,
>  			return 0;
>  	}
>  
> -	event = fanotify_alloc_event(group, inode, mask, data);
> +	if (FAN_GROUP_FLAG(group, FAN_REPORT_FID))
> +		fsid = fanotify_get_fsid(iter_info, &__fsid);
> +
> +	event = fanotify_alloc_event(group, inode, mask, data, fsid);
>  	ret = -ENOMEM;
>  	if (unlikely(!event)) {
>  		/*
> diff --git a/fs/notify/fanotify/fanotify.h b/fs/notify/fanotify/fanotify.h
> index 4aafc7144c3d..5b072afa4e19 100644
> --- a/fs/notify/fanotify/fanotify.h
> +++ b/fs/notify/fanotify/fanotify.h
> @@ -131,5 +131,6 @@ static inline struct fanotify_event *FANOTIFY_E(struct fsnotify_event *fse)
>  }
>  
>  struct fanotify_event *fanotify_alloc_event(struct fsnotify_group *group,
> -						 struct inode *inode, u32 mask,
> -						 const struct path *path);
> +					    struct inode *inode, u32 mask,
> +					    const struct path *path,
> +					    __kernel_fsid_t *fsid);
> diff --git a/fs/notify/fanotify/fanotify_user.c b/fs/notify/fanotify/fanotify_user.c
> index 211ec6332d31..467e6431fbe9 100644
> --- a/fs/notify/fanotify/fanotify_user.c
> +++ b/fs/notify/fanotify/fanotify_user.c
> @@ -653,7 +653,8 @@ static __u32 fanotify_mark_add_to_mask(struct fsnotify_mark *fsn_mark,
>  
>  static struct fsnotify_mark *fanotify_add_new_mark(struct fsnotify_group *group,
>  						   fsnotify_connp_t *connp,
> -						   unsigned int type)
> +						   unsigned int type,
> +						   __kernel_fsid_t *fsid)
>  {
>  	struct fsnotify_mark *mark;
>  	int ret;
> @@ -666,7 +667,7 @@ static struct fsnotify_mark *fanotify_add_new_mark(struct fsnotify_group *group,
>  		return ERR_PTR(-ENOMEM);
>  
>  	fsnotify_init_mark(mark, group);
> -	ret = fsnotify_add_mark_locked(mark, connp, type, 0);
> +	ret = fsnotify_add_mark_locked_fsid(mark, connp, type, 0, fsid);
>  	if (ret) {
>  		fsnotify_put_mark(mark);
>  		return ERR_PTR(ret);
> @@ -678,7 +679,8 @@ static struct fsnotify_mark *fanotify_add_new_mark(struct fsnotify_group *group,
>  
>  static int fanotify_add_mark(struct fsnotify_group *group,
>  			     fsnotify_connp_t *connp, unsigned int type,
> -			     __u32 mask, unsigned int flags)
> +			     __u32 mask, unsigned int flags,
> +			     __kernel_fsid_t *fsid)
>  {
>  	struct fsnotify_mark *fsn_mark;
>  	__u32 added;
> @@ -686,7 +688,7 @@ static int fanotify_add_mark(struct fsnotify_group *group,
>  	mutex_lock(&group->mark_mutex);
>  	fsn_mark = fsnotify_find_mark(connp, group);
>  	if (!fsn_mark) {
> -		fsn_mark = fanotify_add_new_mark(group, connp, type);
> +		fsn_mark = fanotify_add_new_mark(group, connp, type, fsid);
>  		if (IS_ERR(fsn_mark)) {
>  			mutex_unlock(&group->mark_mutex);
>  			return PTR_ERR(fsn_mark);
> @@ -703,23 +705,23 @@ static int fanotify_add_mark(struct fsnotify_group *group,
>  
>  static int fanotify_add_vfsmount_mark(struct fsnotify_group *group,
>  				      struct vfsmount *mnt, __u32 mask,
> -				      unsigned int flags)
> +				      unsigned int flags, __kernel_fsid_t *fsid)
>  {
>  	return fanotify_add_mark(group, &real_mount(mnt)->mnt_fsnotify_marks,
> -				 FSNOTIFY_OBJ_TYPE_VFSMOUNT, mask, flags);
> +				 FSNOTIFY_OBJ_TYPE_VFSMOUNT, mask, flags, fsid);
>  }
>  
>  static int fanotify_add_sb_mark(struct fsnotify_group *group,
> -				      struct super_block *sb, __u32 mask,
> -				      unsigned int flags)
> +				struct super_block *sb, __u32 mask,
> +				unsigned int flags, __kernel_fsid_t *fsid)
>  {
>  	return fanotify_add_mark(group, &sb->s_fsnotify_marks,
> -				 FSNOTIFY_OBJ_TYPE_SB, mask, flags);
> +				 FSNOTIFY_OBJ_TYPE_SB, mask, flags, fsid);
>  }
>  
>  static int fanotify_add_inode_mark(struct fsnotify_group *group,
>  				   struct inode *inode, __u32 mask,
> -				   unsigned int flags)
> +				   unsigned int flags, __kernel_fsid_t *fsid)
>  {
>  	pr_debug("%s: group=%p inode=%p\n", __func__, group, inode);
>  
> @@ -734,7 +736,7 @@ static int fanotify_add_inode_mark(struct fsnotify_group *group,
>  		return 0;
>  
>  	return fanotify_add_mark(group, &inode->i_fsnotify_marks,
> -				 FSNOTIFY_OBJ_TYPE_INODE, mask, flags);
> +				 FSNOTIFY_OBJ_TYPE_INODE, mask, flags, fsid);
>  }
>  
>  /* fanotify syscalls */
> @@ -798,7 +800,7 @@ SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags)
>  	atomic_inc(&user->fanotify_listeners);
>  	group->memcg = get_mem_cgroup_from_mm(current->mm);
>  
> -	oevent = fanotify_alloc_event(group, NULL, FS_Q_OVERFLOW, NULL);
> +	oevent = fanotify_alloc_event(group, NULL, FS_Q_OVERFLOW, NULL, NULL);
>  	if (unlikely(!oevent)) {
>  		fd = -ENOMEM;
>  		goto out_destroy_group;
> @@ -861,9 +863,9 @@ SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags)
>  }
>  
>  /* Check if filesystem can encode a unique fid */
> -static int fanotify_test_fid(struct path *path)
> +static int fanotify_test_fid(struct path *path, struct kstatfs *stat)
>  {
> -	struct kstatfs stat, root_stat;
> +	struct kstatfs root_stat;
>  	struct path root = {
>  		.mnt = path->mnt,
>  		.dentry = path->dentry->d_sb->s_root,
> @@ -873,11 +875,11 @@ static int fanotify_test_fid(struct path *path)
>  	/*
>  	 * Make sure path is not in filesystem with zero fsid (e.g. tmpfs).
>  	 */
> -	err = vfs_statfs(path, &stat);
> +	err = vfs_statfs(path, stat);
>  	if (err)
>  		return err;
>  
> -	if (!stat.f_fsid.val[0] && !stat.f_fsid.val[1])
> +	if (!stat->f_fsid.val[0] && !stat->f_fsid.val[1])
>  		return -ENODEV;
>  
>  	/*
> @@ -888,8 +890,8 @@ static int fanotify_test_fid(struct path *path)
>  	if (err)
>  		return err;
>  
> -	if (root_stat.f_fsid.val[0] != stat.f_fsid.val[0] ||
> -	    root_stat.f_fsid.val[1] != stat.f_fsid.val[1])
> +	if (root_stat.f_fsid.val[0] != stat->f_fsid.val[0] ||
> +	    root_stat.f_fsid.val[1] != stat->f_fsid.val[1])
>  		return -EXDEV;
>  
>  	/*
> @@ -914,6 +916,8 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask,
>  	struct fsnotify_group *group;
>  	struct fd f;
>  	struct path path;
> +	struct kstatfs stat;
> +	__kernel_fsid_t *fsid = NULL;
>  	u32 valid_mask = FANOTIFY_EVENTS | FANOTIFY_EVENT_FLAGS;
>  	unsigned int mark_type = flags & FANOTIFY_MARK_TYPE_BITS;
>  	int ret;
> @@ -992,9 +996,11 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask,
>  		goto fput_and_out;
>  
>  	if (FAN_GROUP_FLAG(group, FAN_REPORT_FID)) {
> -		ret = fanotify_test_fid(&path);
> +		ret = fanotify_test_fid(&path, &stat);
>  		if (ret)
>  			goto path_put_and_out;
> +
> +		fsid = &stat.f_fsid;
>  	}
>  
>  	/* inode held in place by reference to path; group by fget on fd */
> @@ -1007,19 +1013,25 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask,
>  	switch (flags & (FAN_MARK_ADD | FAN_MARK_REMOVE)) {
>  	case FAN_MARK_ADD:
>  		if (mark_type == FAN_MARK_MOUNT)
> -			ret = fanotify_add_vfsmount_mark(group, mnt, mask, flags);
> +			ret = fanotify_add_vfsmount_mark(group, mnt, mask,
> +							 flags, fsid);
>  		else if (mark_type == FAN_MARK_FILESYSTEM)
> -			ret = fanotify_add_sb_mark(group, mnt->mnt_sb, mask, flags);
> +			ret = fanotify_add_sb_mark(group, mnt->mnt_sb, mask,
> +						   flags, fsid);
>  		else
> -			ret = fanotify_add_inode_mark(group, inode, mask, flags);
> +			ret = fanotify_add_inode_mark(group, inode, mask,
> +						      flags, fsid);
>  		break;
>  	case FAN_MARK_REMOVE:
>  		if (mark_type == FAN_MARK_MOUNT)
> -			ret = fanotify_remove_vfsmount_mark(group, mnt, mask, flags);
> +			ret = fanotify_remove_vfsmount_mark(group, mnt, mask,
> +							    flags);
>  		else if (mark_type == FAN_MARK_FILESYSTEM)
> -			ret = fanotify_remove_sb_mark(group, mnt->mnt_sb, mask, flags);
> +			ret = fanotify_remove_sb_mark(group, mnt->mnt_sb, mask,
> +						      flags);
>  		else
> -			ret = fanotify_remove_inode_mark(group, inode, mask, flags);
> +			ret = fanotify_remove_inode_mark(group, inode, mask,
> +							 flags);
>  		break;
>  	default:
>  		ret = -EINVAL;
> diff --git a/fs/notify/mark.c b/fs/notify/mark.c
> index d2dd16cb5989..3c5f39cc7fa3 100644
> --- a/fs/notify/mark.c
> +++ b/fs/notify/mark.c
> @@ -82,6 +82,7 @@
>  #include <linux/slab.h>
>  #include <linux/spinlock.h>
>  #include <linux/srcu.h>
> +#include <linux/ratelimit.h>
>  
>  #include <linux/atomic.h>
>  
> @@ -481,7 +482,8 @@ int fsnotify_compare_groups(struct fsnotify_group *a, struct fsnotify_group *b)
>  }
>  
>  static int fsnotify_attach_connector_to_object(fsnotify_connp_t *connp,
> -					       unsigned int type)
> +					       unsigned int type,
> +					       __kernel_fsid_t *fsid)
>  {
>  	struct inode *inode = NULL;
>  	struct fsnotify_mark_connector *conn;
> @@ -493,6 +495,11 @@ static int fsnotify_attach_connector_to_object(fsnotify_connp_t *connp,
>  	INIT_HLIST_HEAD(&conn->list);
>  	conn->type = type;
>  	conn->obj = connp;
> +	/* Cache fsid of filesystem containing the object */
> +	if (fsid)
> +		conn->fsid = *fsid;
> +	else
> +		conn->fsid.val[0] = conn->fsid.val[1] = 0;
>  	if (conn->type == FSNOTIFY_OBJ_TYPE_INODE)
>  		inode = igrab(fsnotify_conn_inode(conn));
>  	/*
> @@ -544,7 +551,7 @@ static struct fsnotify_mark_connector *fsnotify_grab_connector(
>   */
>  static int fsnotify_add_mark_list(struct fsnotify_mark *mark,
>  				  fsnotify_connp_t *connp, unsigned int type,
> -				  int allow_dups)
> +				  int allow_dups, __kernel_fsid_t *fsid)
>  {
>  	struct fsnotify_mark *lmark, *last = NULL;
>  	struct fsnotify_mark_connector *conn;
> @@ -553,15 +560,36 @@ static int fsnotify_add_mark_list(struct fsnotify_mark *mark,
>  
>  	if (WARN_ON(!fsnotify_valid_obj_type(type)))
>  		return -EINVAL;
> +
> +	/* Backend is expected to check for zero fsid (e.g. tmpfs) */
> +	if (fsid && WARN_ON_ONCE(!fsid->val[0] && !fsid->val[1]))
> +		return -ENODEV;
> +
>  restart:
>  	spin_lock(&mark->lock);
>  	conn = fsnotify_grab_connector(connp);
>  	if (!conn) {
>  		spin_unlock(&mark->lock);
> -		err = fsnotify_attach_connector_to_object(connp, type);
> +		err = fsnotify_attach_connector_to_object(connp, type, fsid);
>  		if (err)
>  			return err;
>  		goto restart;
> +	} else if (fsid && (conn->fsid.val[0] || conn->fsid.val[1]) &&
> +		   (fsid->val[0] != conn->fsid.val[0] ||
> +		    fsid->val[1] != conn->fsid.val[1])) {
> +		/*
> +		 * Backend is expected to check for non uniform fsid
> +		 * (e.g. btrfs), but maybe we missed something?
> +		 * Only allow setting conn->fsid once to non zero fsid.
> +		 * inotify and non-fid fanotify groups do not set nor test
> +		 * conn->fsid.
> +		 */
> +		pr_warn_ratelimited("%s: fsid mismatch on object of type %u: %x.%x != %x.%x\n",
> +				    __func__, conn->type,
> +				    fsid->val[0], fsid->val[1],
> +				    conn->fsid.val[0], conn->fsid.val[1]);
> +		err = -EXDEV;
> +		goto out_err;
>  	}
>  
>  	/* is mark the first mark? */
> @@ -604,9 +632,9 @@ static int fsnotify_add_mark_list(struct fsnotify_mark *mark,
>   * These marks may be used for the fsnotify backend to determine which
>   * event types should be delivered to which group.
>   */
> -int fsnotify_add_mark_locked(struct fsnotify_mark *mark,
> -			     fsnotify_connp_t *connp, unsigned int type,
> -			     int allow_dups)
> +int fsnotify_add_mark_locked_fsid(struct fsnotify_mark *mark,
> +				  fsnotify_connp_t *connp, unsigned int type,
> +				  int allow_dups, __kernel_fsid_t *fsid)
>  {
>  	struct fsnotify_group *group = mark->group;
>  	int ret = 0;
> @@ -627,7 +655,7 @@ int fsnotify_add_mark_locked(struct fsnotify_mark *mark,
>  	fsnotify_get_mark(mark); /* for g_list */
>  	spin_unlock(&mark->lock);
>  
> -	ret = fsnotify_add_mark_list(mark, connp, type, allow_dups);
> +	ret = fsnotify_add_mark_list(mark, connp, type, allow_dups, fsid);
>  	if (ret)
>  		goto err;
>  
> @@ -648,13 +676,14 @@ int fsnotify_add_mark_locked(struct fsnotify_mark *mark,
>  }
>  
>  int fsnotify_add_mark(struct fsnotify_mark *mark, fsnotify_connp_t *connp,
> -		      unsigned int type, int allow_dups)
> +		      unsigned int type, int allow_dups, __kernel_fsid_t *fsid)
>  {
>  	int ret;
>  	struct fsnotify_group *group = mark->group;
>  
>  	mutex_lock(&group->mark_mutex);
> -	ret = fsnotify_add_mark_locked(mark, connp, type, allow_dups);
> +	ret = fsnotify_add_mark_locked_fsid(mark, connp, type, allow_dups,
> +					    fsid);
>  	mutex_unlock(&group->mark_mutex);
>  	return ret;
>  }
> diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h
> index 1e4b88bd1443..b66c4199d629 100644
> --- a/include/linux/fsnotify_backend.h
> +++ b/include/linux/fsnotify_backend.h
> @@ -293,6 +293,7 @@ typedef struct fsnotify_mark_connector __rcu *fsnotify_connp_t;
>  struct fsnotify_mark_connector {
>  	spinlock_t lock;
>  	unsigned int type;	/* Type of object [lock] */
> +	__kernel_fsid_t fsid;	/* fsid of filesystem containing object */
>  	union {
>  		/* Object pointer [lock] */
>  		fsnotify_connp_t *obj;
> @@ -433,20 +434,32 @@ extern void fsnotify_init_mark(struct fsnotify_mark *mark,
>  /* Find mark belonging to given group in the list of marks */
>  extern struct fsnotify_mark *fsnotify_find_mark(fsnotify_connp_t *connp,
>  						struct fsnotify_group *group);
> +/* Get cached fsid of filesystem containing object */
> +extern int fsnotify_get_conn_fsid(const struct fsnotify_mark_connector *conn,
> +				  __kernel_fsid_t *fsid);
>  /* attach the mark to the object */
>  extern int fsnotify_add_mark(struct fsnotify_mark *mark,
>  			     fsnotify_connp_t *connp, unsigned int type,
> -			     int allow_dups);
> -extern int fsnotify_add_mark_locked(struct fsnotify_mark *mark,
> -				    fsnotify_connp_t *connp, unsigned int type,
> -				    int allow_dups);
> +			     int allow_dups, __kernel_fsid_t *fsid);
> +extern int fsnotify_add_mark_locked_fsid(struct fsnotify_mark *mark,
> +					 fsnotify_connp_t *connp,
> +					 unsigned int type, int allow_dups,
> +					 __kernel_fsid_t *fsid);
> +static inline int fsnotify_add_mark_locked(struct fsnotify_mark *mark,
> +					   fsnotify_connp_t *connp,
> +					   unsigned int type, int allow_dups)
> +{
> +	return fsnotify_add_mark_locked_fsid(mark, connp, type, allow_dups,
> +					     NULL);
> +}
> +
>  /* attach the mark to the inode */
>  static inline int fsnotify_add_inode_mark(struct fsnotify_mark *mark,
>  					  struct inode *inode,
>  					  int allow_dups)
>  {
>  	return fsnotify_add_mark(mark, &inode->i_fsnotify_marks,
> -				 FSNOTIFY_OBJ_TYPE_INODE, allow_dups);
> +				 FSNOTIFY_OBJ_TYPE_INODE, allow_dups, NULL);
>  }
>  static inline int fsnotify_add_inode_mark_locked(struct fsnotify_mark *mark,
>  						 struct inode *inode,
> @@ -455,6 +468,7 @@ static inline int fsnotify_add_inode_mark_locked(struct fsnotify_mark *mark,
>  	return fsnotify_add_mark_locked(mark, &inode->i_fsnotify_marks,
>  					FSNOTIFY_OBJ_TYPE_INODE, allow_dups);
>  }
> +
>  /* given a group and a mark, flag mark to be freed when all references are dropped */
>  extern void fsnotify_destroy_mark(struct fsnotify_mark *mark,
>  				  struct fsnotify_group *group);
> -- 
> 2.17.1
> 
-- 
Jan Kara <jack@suse.com>
SUSE Labs, CR

[-- Attachment #2: 0001-fanotify-cache-fsid-in-fsnotify_mark_connector.patch --]
[-- Type: text/x-patch, Size: 18909 bytes --]

From 9d8b60cea74117acea8e5b5d8876bd0094f734b1 Mon Sep 17 00:00:00 2001
From: Amir Goldstein <amir73il@gmail.com>
Date: Thu, 10 Jan 2019 19:04:37 +0200
Subject: [PATCH] fanotify: cache fsid in fsnotify_mark_connector

For FAN_REPORT_FID, we need to encode fid with fsid of the filesystem on
every event. To avoid having to call vfs_statfs() on every event to get
fsid, we store the fsid in fsnotify_mark_connector on the first time we
add a mark and on handle event we use the cached fsid.

Subsequent calls to add mark on the same object are expected to pass the
same fsid, so the call will fail on cached fsid mismatch.

If an event is reported on several mark types (inode, mount, filesystem),
all connectors should already have the same fsid, so we use the cached
fsid from the first connector.

[JK: Simplify code flow around fanotify_get_fid()
     make fsid argument of fsnotify_add_mark_locked() unconditional]

Suggested-by: Jan Kara <jack@suse.cz>
Signed-off-by: Amir Goldstein <amir73il@gmail.com>
Signed-off-by: Jan Kara <jack@suse.cz>
---
 fs/notify/fanotify/fanotify.c      | 50 ++++++++++++++++++++---------
 fs/notify/fanotify/fanotify.h      |  5 +--
 fs/notify/fanotify/fanotify_user.c | 64 ++++++++++++++++++++++----------------
 fs/notify/mark.c                   | 42 ++++++++++++++++++++-----
 include/linux/fsnotify_backend.h   | 18 ++++++++---
 5 files changed, 125 insertions(+), 54 deletions(-)

diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c
index b19b049746a1..0815593562d7 100644
--- a/fs/notify/fanotify/fanotify.c
+++ b/fs/notify/fanotify/fanotify.c
@@ -153,14 +153,13 @@ static u32 fanotify_group_event_mask(struct fsnotify_iter_info *iter_info,
 }
 
 static int fanotify_encode_fid(struct fanotify_event *event,
-			       const struct path *path, gfp_t gfp)
+			       const struct path *path, gfp_t gfp,
+			       __kernel_fsid_t *fsid)
 {
 	struct fanotify_fid *fid = &event->fid;
 	int dwords, bytes = 0;
-	struct kstatfs stat;
 	int err, type;
 
-	stat.f_fsid.val[0] = stat.f_fsid.val[1] = 0;
 	fid->ext_fh = NULL;
 	dwords = 0;
 	err = -ENOENT;
@@ -168,10 +167,6 @@ static int fanotify_encode_fid(struct fanotify_event *event,
 	if (!dwords)
 		goto out_err;
 
-	err = vfs_statfs(path, &stat);
-	if (err)
-		goto out_err;
-
 	bytes = dwords << 2;
 	if (bytes > FANOTIFY_INLINE_FH_LEN) {
 		/* Treat failure to allocate fh as failure to allocate event */
@@ -187,7 +182,7 @@ static int fanotify_encode_fid(struct fanotify_event *event,
 	if (!type || type == FILEID_INVALID || bytes != dwords << 2)
 		goto out_err;
 
-	fid->fsid = stat.f_fsid;
+	fid->fsid = *fsid;
 	event->fh_len = bytes;
 
 	return type;
@@ -195,8 +190,7 @@ static int fanotify_encode_fid(struct fanotify_event *event,
 out_err:
 	pr_warn_ratelimited("fanotify: failed to encode fid (fsid=%x.%x, "
 			    "type=%d, bytes=%d, err=%i)\n",
-			    stat.f_fsid.val[0], stat.f_fsid.val[1],
-			    type, bytes, err);
+			    fsid->val[0], fsid->val[1], type, bytes, err);
 	kfree(fid->ext_fh);
 	fid->ext_fh = NULL;
 	event->fh_len = 0;
@@ -205,8 +199,9 @@ static int fanotify_encode_fid(struct fanotify_event *event,
 }
 
 struct fanotify_event *fanotify_alloc_event(struct fsnotify_group *group,
-						 struct inode *inode, u32 mask,
-						 const struct path *path)
+					    struct inode *inode, u32 mask,
+					    const struct path *path,
+					    __kernel_fsid_t *fsid)
 {
 	struct fanotify_event *event = NULL;
 	gfp_t gfp = GFP_KERNEL_ACCOUNT;
@@ -245,7 +240,7 @@ init: __maybe_unused
 	event->fh_len = 0;
 	if (path && FAN_GROUP_FLAG(group, FAN_REPORT_FID)) {
 		/* Report the event without a file identifier on encode error */
-		event->fh_type = fanotify_encode_fid(event, path, gfp);
+		event->fh_type = fanotify_encode_fid(event, path, gfp, fsid);
 	} else if (path) {
 		event->fh_type = FILEID_ROOT;
 		event->path = *path;
@@ -260,6 +255,29 @@ init: __maybe_unused
 	return event;
 }
 
+/*
+ * Get cached fsid of the filesystem containing the object from any connector.
+ * All connectors are supposed to have the same fsid, but we do not verify that
+ * here.
+ */
+static __kernel_fsid_t fanotify_get_fsid(struct fsnotify_iter_info *iter_info)
+{
+	int type;
+	__kernel_fsid_t fsid = {};
+
+	fsnotify_foreach_obj_type(type) {
+		if (!fsnotify_iter_should_report_type(iter_info, type))
+			continue;
+
+		fsid = iter_info->marks[type]->connector->fsid;
+		if (WARN_ON_ONCE(!fsid.val[0] && !fsid.val[1]))
+			continue;
+		return fsid;
+	}
+
+	return fsid;
+}
+
 static int fanotify_handle_event(struct fsnotify_group *group,
 				 struct inode *inode,
 				 u32 mask, const void *data, int data_type,
@@ -269,6 +287,7 @@ static int fanotify_handle_event(struct fsnotify_group *group,
 	int ret = 0;
 	struct fanotify_event *event;
 	struct fsnotify_event *fsn_event;
+	__kernel_fsid_t fsid = {};
 
 	BUILD_BUG_ON(FAN_ACCESS != FS_ACCESS);
 	BUILD_BUG_ON(FAN_MODIFY != FS_MODIFY);
@@ -301,7 +320,10 @@ static int fanotify_handle_event(struct fsnotify_group *group,
 			return 0;
 	}
 
-	event = fanotify_alloc_event(group, inode, mask, data);
+	if (FAN_GROUP_FLAG(group, FAN_REPORT_FID))
+		fsid = fanotify_get_fsid(iter_info);
+
+	event = fanotify_alloc_event(group, inode, mask, data, &fsid);
 	ret = -ENOMEM;
 	if (unlikely(!event)) {
 		/*
diff --git a/fs/notify/fanotify/fanotify.h b/fs/notify/fanotify/fanotify.h
index 4aafc7144c3d..5b072afa4e19 100644
--- a/fs/notify/fanotify/fanotify.h
+++ b/fs/notify/fanotify/fanotify.h
@@ -131,5 +131,6 @@ static inline struct fanotify_event *FANOTIFY_E(struct fsnotify_event *fse)
 }
 
 struct fanotify_event *fanotify_alloc_event(struct fsnotify_group *group,
-						 struct inode *inode, u32 mask,
-						 const struct path *path);
+					    struct inode *inode, u32 mask,
+					    const struct path *path,
+					    __kernel_fsid_t *fsid);
diff --git a/fs/notify/fanotify/fanotify_user.c b/fs/notify/fanotify/fanotify_user.c
index a09bc7d1ab87..603419ce096f 100644
--- a/fs/notify/fanotify/fanotify_user.c
+++ b/fs/notify/fanotify/fanotify_user.c
@@ -246,7 +246,7 @@ static ssize_t copy_event_to_user(struct fsnotify_group *group,
 {
 	struct fanotify_event_metadata metadata;
 	struct fanotify_event *event;
-	struct file *f;
+	struct file *f = NULL;
 	int ret, fd = FAN_NOFD;
 
 	pr_debug("%s: group=%p event=%p\n", __func__, group, fsn_event);
@@ -653,7 +653,8 @@ static __u32 fanotify_mark_add_to_mask(struct fsnotify_mark *fsn_mark,
 
 static struct fsnotify_mark *fanotify_add_new_mark(struct fsnotify_group *group,
 						   fsnotify_connp_t *connp,
-						   unsigned int type)
+						   unsigned int type,
+						   __kernel_fsid_t *fsid)
 {
 	struct fsnotify_mark *mark;
 	int ret;
@@ -666,7 +667,7 @@ static struct fsnotify_mark *fanotify_add_new_mark(struct fsnotify_group *group,
 		return ERR_PTR(-ENOMEM);
 
 	fsnotify_init_mark(mark, group);
-	ret = fsnotify_add_mark_locked(mark, connp, type, 0);
+	ret = fsnotify_add_mark_locked(mark, connp, type, 0, fsid);
 	if (ret) {
 		fsnotify_put_mark(mark);
 		return ERR_PTR(ret);
@@ -678,7 +679,8 @@ static struct fsnotify_mark *fanotify_add_new_mark(struct fsnotify_group *group,
 
 static int fanotify_add_mark(struct fsnotify_group *group,
 			     fsnotify_connp_t *connp, unsigned int type,
-			     __u32 mask, unsigned int flags)
+			     __u32 mask, unsigned int flags,
+			     __kernel_fsid_t *fsid)
 {
 	struct fsnotify_mark *fsn_mark;
 	__u32 added;
@@ -686,7 +688,7 @@ static int fanotify_add_mark(struct fsnotify_group *group,
 	mutex_lock(&group->mark_mutex);
 	fsn_mark = fsnotify_find_mark(connp, group);
 	if (!fsn_mark) {
-		fsn_mark = fanotify_add_new_mark(group, connp, type);
+		fsn_mark = fanotify_add_new_mark(group, connp, type, fsid);
 		if (IS_ERR(fsn_mark)) {
 			mutex_unlock(&group->mark_mutex);
 			return PTR_ERR(fsn_mark);
@@ -703,23 +705,23 @@ static int fanotify_add_mark(struct fsnotify_group *group,
 
 static int fanotify_add_vfsmount_mark(struct fsnotify_group *group,
 				      struct vfsmount *mnt, __u32 mask,
-				      unsigned int flags)
+				      unsigned int flags, __kernel_fsid_t *fsid)
 {
 	return fanotify_add_mark(group, &real_mount(mnt)->mnt_fsnotify_marks,
-				 FSNOTIFY_OBJ_TYPE_VFSMOUNT, mask, flags);
+				 FSNOTIFY_OBJ_TYPE_VFSMOUNT, mask, flags, fsid);
 }
 
 static int fanotify_add_sb_mark(struct fsnotify_group *group,
-				      struct super_block *sb, __u32 mask,
-				      unsigned int flags)
+				struct super_block *sb, __u32 mask,
+				unsigned int flags, __kernel_fsid_t *fsid)
 {
 	return fanotify_add_mark(group, &sb->s_fsnotify_marks,
-				 FSNOTIFY_OBJ_TYPE_SB, mask, flags);
+				 FSNOTIFY_OBJ_TYPE_SB, mask, flags, fsid);
 }
 
 static int fanotify_add_inode_mark(struct fsnotify_group *group,
 				   struct inode *inode, __u32 mask,
-				   unsigned int flags)
+				   unsigned int flags, __kernel_fsid_t *fsid)
 {
 	pr_debug("%s: group=%p inode=%p\n", __func__, group, inode);
 
@@ -734,7 +736,7 @@ static int fanotify_add_inode_mark(struct fsnotify_group *group,
 		return 0;
 
 	return fanotify_add_mark(group, &inode->i_fsnotify_marks,
-				 FSNOTIFY_OBJ_TYPE_INODE, mask, flags);
+				 FSNOTIFY_OBJ_TYPE_INODE, mask, flags, fsid);
 }
 
 /* fanotify syscalls */
@@ -798,7 +800,7 @@ SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags)
 	atomic_inc(&user->fanotify_listeners);
 	group->memcg = get_mem_cgroup_from_mm(current->mm);
 
-	oevent = fanotify_alloc_event(group, NULL, FS_Q_OVERFLOW, NULL);
+	oevent = fanotify_alloc_event(group, NULL, FS_Q_OVERFLOW, NULL, NULL);
 	if (unlikely(!oevent)) {
 		fd = -ENOMEM;
 		goto out_destroy_group;
@@ -861,9 +863,9 @@ SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags)
 }
 
 /* Check if filesystem can encode a unique fid */
-static int fanotify_test_fid(struct path *path)
+static int fanotify_test_fid(struct path *path, struct kstatfs *stat)
 {
-	struct kstatfs stat, root_stat;
+	struct kstatfs root_stat;
 	struct path root = {
 		.mnt = path->mnt,
 		.dentry = path->dentry->d_sb->s_root,
@@ -873,11 +875,11 @@ static int fanotify_test_fid(struct path *path)
 	/*
 	 * Make sure path is not in filesystem with zero fsid (e.g. tmpfs).
 	 */
-	err = vfs_statfs(path, &stat);
+	err = vfs_statfs(path, stat);
 	if (err)
 		return err;
 
-	if (!stat.f_fsid.val[0] && !stat.f_fsid.val[1])
+	if (!stat->f_fsid.val[0] && !stat->f_fsid.val[1])
 		return -ENODEV;
 
 	/*
@@ -888,8 +890,8 @@ static int fanotify_test_fid(struct path *path)
 	if (err)
 		return err;
 
-	if (root_stat.f_fsid.val[0] != stat.f_fsid.val[0] ||
-	    root_stat.f_fsid.val[1] != stat.f_fsid.val[1])
+	if (root_stat.f_fsid.val[0] != stat->f_fsid.val[0] ||
+	    root_stat.f_fsid.val[1] != stat->f_fsid.val[1])
 		return -EXDEV;
 
 	/*
@@ -914,6 +916,8 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask,
 	struct fsnotify_group *group;
 	struct fd f;
 	struct path path;
+	struct kstatfs stat;
+	__kernel_fsid_t *fsid = NULL;
 	u32 valid_mask = FANOTIFY_EVENTS | FANOTIFY_EVENT_FLAGS;
 	unsigned int mark_type = flags & FANOTIFY_MARK_TYPE_BITS;
 	int ret;
@@ -992,9 +996,11 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask,
 		goto fput_and_out;
 
 	if (FAN_GROUP_FLAG(group, FAN_REPORT_FID)) {
-		ret = fanotify_test_fid(&path);
+		ret = fanotify_test_fid(&path, &stat);
 		if (ret)
 			goto path_put_and_out;
+
+		fsid = &stat.f_fsid;
 	}
 
 	/* inode held in place by reference to path; group by fget on fd */
@@ -1007,19 +1013,25 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask,
 	switch (flags & (FAN_MARK_ADD | FAN_MARK_REMOVE)) {
 	case FAN_MARK_ADD:
 		if (mark_type == FAN_MARK_MOUNT)
-			ret = fanotify_add_vfsmount_mark(group, mnt, mask, flags);
+			ret = fanotify_add_vfsmount_mark(group, mnt, mask,
+							 flags, fsid);
 		else if (mark_type == FAN_MARK_FILESYSTEM)
-			ret = fanotify_add_sb_mark(group, mnt->mnt_sb, mask, flags);
+			ret = fanotify_add_sb_mark(group, mnt->mnt_sb, mask,
+						   flags, fsid);
 		else
-			ret = fanotify_add_inode_mark(group, inode, mask, flags);
+			ret = fanotify_add_inode_mark(group, inode, mask,
+						      flags, fsid);
 		break;
 	case FAN_MARK_REMOVE:
 		if (mark_type == FAN_MARK_MOUNT)
-			ret = fanotify_remove_vfsmount_mark(group, mnt, mask, flags);
+			ret = fanotify_remove_vfsmount_mark(group, mnt, mask,
+							    flags);
 		else if (mark_type == FAN_MARK_FILESYSTEM)
-			ret = fanotify_remove_sb_mark(group, mnt->mnt_sb, mask, flags);
+			ret = fanotify_remove_sb_mark(group, mnt->mnt_sb, mask,
+						      flags);
 		else
-			ret = fanotify_remove_inode_mark(group, inode, mask, flags);
+			ret = fanotify_remove_inode_mark(group, inode, mask,
+							 flags);
 		break;
 	default:
 		ret = -EINVAL;
diff --git a/fs/notify/mark.c b/fs/notify/mark.c
index d2dd16cb5989..d593d4269561 100644
--- a/fs/notify/mark.c
+++ b/fs/notify/mark.c
@@ -82,6 +82,7 @@
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/srcu.h>
+#include <linux/ratelimit.h>
 
 #include <linux/atomic.h>
 
@@ -481,7 +482,8 @@ int fsnotify_compare_groups(struct fsnotify_group *a, struct fsnotify_group *b)
 }
 
 static int fsnotify_attach_connector_to_object(fsnotify_connp_t *connp,
-					       unsigned int type)
+					       unsigned int type,
+					       __kernel_fsid_t *fsid)
 {
 	struct inode *inode = NULL;
 	struct fsnotify_mark_connector *conn;
@@ -493,6 +495,11 @@ static int fsnotify_attach_connector_to_object(fsnotify_connp_t *connp,
 	INIT_HLIST_HEAD(&conn->list);
 	conn->type = type;
 	conn->obj = connp;
+	/* Cache fsid of filesystem containing the object */
+	if (fsid)
+		conn->fsid = *fsid;
+	else
+		conn->fsid.val[0] = conn->fsid.val[1] = 0;
 	if (conn->type == FSNOTIFY_OBJ_TYPE_INODE)
 		inode = igrab(fsnotify_conn_inode(conn));
 	/*
@@ -544,7 +551,7 @@ static struct fsnotify_mark_connector *fsnotify_grab_connector(
  */
 static int fsnotify_add_mark_list(struct fsnotify_mark *mark,
 				  fsnotify_connp_t *connp, unsigned int type,
-				  int allow_dups)
+				  int allow_dups, __kernel_fsid_t *fsid)
 {
 	struct fsnotify_mark *lmark, *last = NULL;
 	struct fsnotify_mark_connector *conn;
@@ -553,15 +560,36 @@ static int fsnotify_add_mark_list(struct fsnotify_mark *mark,
 
 	if (WARN_ON(!fsnotify_valid_obj_type(type)))
 		return -EINVAL;
+
+	/* Backend is expected to check for zero fsid (e.g. tmpfs) */
+	if (fsid && WARN_ON_ONCE(!fsid->val[0] && !fsid->val[1]))
+		return -ENODEV;
+
 restart:
 	spin_lock(&mark->lock);
 	conn = fsnotify_grab_connector(connp);
 	if (!conn) {
 		spin_unlock(&mark->lock);
-		err = fsnotify_attach_connector_to_object(connp, type);
+		err = fsnotify_attach_connector_to_object(connp, type, fsid);
 		if (err)
 			return err;
 		goto restart;
+	} else if (fsid && (conn->fsid.val[0] || conn->fsid.val[1]) &&
+		   (fsid->val[0] != conn->fsid.val[0] ||
+		    fsid->val[1] != conn->fsid.val[1])) {
+		/*
+		 * Backend is expected to check for non uniform fsid
+		 * (e.g. btrfs), but maybe we missed something?
+		 * Only allow setting conn->fsid once to non zero fsid.
+		 * inotify and non-fid fanotify groups do not set nor test
+		 * conn->fsid.
+		 */
+		pr_warn_ratelimited("%s: fsid mismatch on object of type %u: "
+				    "%x.%x != %x.%x\n", __func__, conn->type,
+				    fsid->val[0], fsid->val[1],
+				    conn->fsid.val[0], conn->fsid.val[1]);
+		err = -EXDEV;
+		goto out_err;
 	}
 
 	/* is mark the first mark? */
@@ -606,7 +634,7 @@ static int fsnotify_add_mark_list(struct fsnotify_mark *mark,
  */
 int fsnotify_add_mark_locked(struct fsnotify_mark *mark,
 			     fsnotify_connp_t *connp, unsigned int type,
-			     int allow_dups)
+			     int allow_dups, __kernel_fsid_t *fsid)
 {
 	struct fsnotify_group *group = mark->group;
 	int ret = 0;
@@ -627,7 +655,7 @@ int fsnotify_add_mark_locked(struct fsnotify_mark *mark,
 	fsnotify_get_mark(mark); /* for g_list */
 	spin_unlock(&mark->lock);
 
-	ret = fsnotify_add_mark_list(mark, connp, type, allow_dups);
+	ret = fsnotify_add_mark_list(mark, connp, type, allow_dups, fsid);
 	if (ret)
 		goto err;
 
@@ -648,13 +676,13 @@ int fsnotify_add_mark_locked(struct fsnotify_mark *mark,
 }
 
 int fsnotify_add_mark(struct fsnotify_mark *mark, fsnotify_connp_t *connp,
-		      unsigned int type, int allow_dups)
+		      unsigned int type, int allow_dups, __kernel_fsid_t *fsid)
 {
 	int ret;
 	struct fsnotify_group *group = mark->group;
 
 	mutex_lock(&group->mark_mutex);
-	ret = fsnotify_add_mark_locked(mark, connp, type, allow_dups);
+	ret = fsnotify_add_mark_locked(mark, connp, type, allow_dups, fsid);
 	mutex_unlock(&group->mark_mutex);
 	return ret;
 }
diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h
index 1e4b88bd1443..7b93f15b4944 100644
--- a/include/linux/fsnotify_backend.h
+++ b/include/linux/fsnotify_backend.h
@@ -293,6 +293,7 @@ typedef struct fsnotify_mark_connector __rcu *fsnotify_connp_t;
 struct fsnotify_mark_connector {
 	spinlock_t lock;
 	unsigned int type;	/* Type of object [lock] */
+	__kernel_fsid_t fsid;	/* fsid of filesystem containing object */
 	union {
 		/* Object pointer [lock] */
 		fsnotify_connp_t *obj;
@@ -433,28 +434,35 @@ extern void fsnotify_init_mark(struct fsnotify_mark *mark,
 /* Find mark belonging to given group in the list of marks */
 extern struct fsnotify_mark *fsnotify_find_mark(fsnotify_connp_t *connp,
 						struct fsnotify_group *group);
+/* Get cached fsid of filesystem containing object */
+extern int fsnotify_get_conn_fsid(const struct fsnotify_mark_connector *conn,
+				  __kernel_fsid_t *fsid);
 /* attach the mark to the object */
 extern int fsnotify_add_mark(struct fsnotify_mark *mark,
 			     fsnotify_connp_t *connp, unsigned int type,
-			     int allow_dups);
+			     int allow_dups, __kernel_fsid_t *fsid);
 extern int fsnotify_add_mark_locked(struct fsnotify_mark *mark,
-				    fsnotify_connp_t *connp, unsigned int type,
-				    int allow_dups);
+				    fsnotify_connp_t *connp,
+				    unsigned int type, int allow_dups,
+				    __kernel_fsid_t *fsid);
+
 /* attach the mark to the inode */
 static inline int fsnotify_add_inode_mark(struct fsnotify_mark *mark,
 					  struct inode *inode,
 					  int allow_dups)
 {
 	return fsnotify_add_mark(mark, &inode->i_fsnotify_marks,
-				 FSNOTIFY_OBJ_TYPE_INODE, allow_dups);
+				 FSNOTIFY_OBJ_TYPE_INODE, allow_dups, NULL);
 }
 static inline int fsnotify_add_inode_mark_locked(struct fsnotify_mark *mark,
 						 struct inode *inode,
 						 int allow_dups)
 {
 	return fsnotify_add_mark_locked(mark, &inode->i_fsnotify_marks,
-					FSNOTIFY_OBJ_TYPE_INODE, allow_dups);
+					FSNOTIFY_OBJ_TYPE_INODE, allow_dups,
+					NULL);
 }
+
 /* given a group and a mark, flag mark to be freed when all references are dropped */
 extern void fsnotify_destroy_mark(struct fsnotify_mark *mark,
 				  struct fsnotify_group *group);
-- 
2.16.4


^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH v5 13/17] fsnotify: report FS_ISDIR flag with MOVE_SELF and DELETE_SELF events
  2019-01-10 17:04 ` [PATCH v5 13/17] fsnotify: report FS_ISDIR flag with MOVE_SELF and DELETE_SELF events Amir Goldstein
@ 2019-02-07 14:57   ` Jan Kara
  0 siblings, 0 replies; 34+ messages in thread
From: Jan Kara @ 2019-02-07 14:57 UTC (permalink / raw)
  To: Amir Goldstein; +Cc: Jan Kara, Matthew Bobrowski, linux-fsdevel

On Thu 10-01-19 19:04:40, Amir Goldstein wrote:
> @@ -111,6 +118,9 @@ static inline void fsnotify_move(struct inode *old_dir, struct inode *new_dir,
>  		new_dir_mask |= FS_ISDIR;
>  	}
>  
> +	if (d_is_dir(moved))
> +		mask |= FS_ISDIR;
> +
>  	fsnotify(old_dir, old_dir_mask, source, FSNOTIFY_EVENT_INODE, old_name,
>  		 fs_cookie);
>  	fsnotify(new_dir, new_dir_mask, source, FSNOTIFY_EVENT_INODE, new_name,

The 'isdir' argument of fsnotify_move() is exactly d_is_dir(moved). So I've
simplified the code by:

        if (isdir) {
                old_dir_mask |= FS_ISDIR;
                new_dir_mask |= FS_ISDIR;
-       }
-
-       if (d_is_dir(moved))
                mask |= FS_ISDIR;
+       }

								Honza
-- 
Jan Kara <jack@suse.com>
SUSE Labs, CR

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH v5 15/17] fanotify: support events with data type FSNOTIFY_EVENT_INODE
  2019-01-10 17:04 ` [PATCH v5 15/17] fanotify: support events with data type FSNOTIFY_EVENT_INODE Amir Goldstein
@ 2019-02-07 15:18   ` Jan Kara
  2019-02-07 16:10     ` Amir Goldstein
  0 siblings, 1 reply; 34+ messages in thread
From: Jan Kara @ 2019-02-07 15:18 UTC (permalink / raw)
  To: Amir Goldstein; +Cc: Jan Kara, Matthew Bobrowski, linux-fsdevel

On Thu 10-01-19 19:04:42, Amir Goldstein wrote:
> When event data type is FSNOTIFY_EVENT_INODE, we don't have a refernece
> to the mount, so we will not be able to open a file descriptor when user
> reads the event. However, if the listener has enabled reporting file
> identifier with the FAN_REPORT_FID init flag, we allow reporting those
> events and we use an identifier inode to encode fid.
> 
> The inode to use as identifier when reporting fid depends on the event.
> For dirent modification events, we report the modified directory inode
> and we report the "victim" inode otherwise.
> For example:
> FS_ATTRIB reports the child inode even if reported on a watched parent.
> FS_CREATE reports the modified dir inode and not the created inode.
> 
> Signed-off-by: Amir Goldstein <amir73il@gmail.com>
> ---
>  fs/notify/fanotify/fanotify.c      | 67 ++++++++++++++++++++----------
>  fs/notify/fanotify/fanotify.h      |  2 +-
>  fs/notify/fanotify/fanotify_user.c |  3 +-
>  3 files changed, 48 insertions(+), 24 deletions(-)
> 
> diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c
> index fcb98ea99508..e3ca1632feb8 100644
> --- a/fs/notify/fanotify/fanotify.c
> +++ b/fs/notify/fanotify/fanotify.c
> @@ -96,7 +96,7 @@ static int fanotify_get_response(struct fsnotify_group *group,
>  
>  	pr_debug("%s: group=%p event=%p about to return ret=%d\n", __func__,
>  		 group, event, ret);
> -	
> +
>  	return ret;
>  }
>  
> @@ -106,9 +106,10 @@ static int fanotify_get_response(struct fsnotify_group *group,
>   * been included within the event mask, but have not been explicitly
>   * requested by the user, will not be present in the returned mask.
>   */
> -static u32 fanotify_group_event_mask(struct fsnotify_iter_info *iter_info,
> -				       u32 event_mask, const void *data,
> -				       int data_type)
> +static u32 fanotify_group_event_mask(struct fsnotify_group *group,
> +				     struct fsnotify_iter_info *iter_info,
> +				     u32 event_mask, const void *data,
> +				     int data_type)
>  {
>  	__u32 marks_mask = 0, marks_ignored_mask = 0;
>  	const struct path *path = data;
> @@ -118,14 +119,14 @@ static u32 fanotify_group_event_mask(struct fsnotify_iter_info *iter_info,
>  	pr_debug("%s: report_mask=%x mask=%x data=%p data_type=%d\n",
>  		 __func__, iter_info->report_mask, event_mask, data, data_type);
>  
> -	/* If we don't have enough info to send an event to userspace say no */
> -	if (data_type != FSNOTIFY_EVENT_PATH)
> -		return 0;
> -
> -	/* Sorry, fanotify only gives a damn about files and dirs */
> -	if (!d_is_reg(path->dentry) &&
> -	    !d_can_lookup(path->dentry))
> +	if (data_type == FSNOTIFY_EVENT_PATH) {
> +		/* Path type events are only relevant for files and dirs */
> +		if (!d_is_reg(path->dentry) && !d_can_lookup(path->dentry))
> +			return 0;

Hum, does this mean that fanotify won't report O_PATH open on symlink
unlike inotify? So shouldn't the condition rather be:

	if (!FAN_GROUP_FLAG(group, FAN_REPORT_FID)) {
		if (data_type != FSNOTIFY_EVENT_PATH)
			return 0;
		if (!d_is_reg(path->dentry) && !d_can_lookup(path->dentry))
			return 0;
	}

?
								Honza

-- 
Jan Kara <jack@suse.com>
SUSE Labs, CR

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH v5 15/17] fanotify: support events with data type FSNOTIFY_EVENT_INODE
  2019-02-07 15:18   ` Jan Kara
@ 2019-02-07 16:10     ` Amir Goldstein
  0 siblings, 0 replies; 34+ messages in thread
From: Amir Goldstein @ 2019-02-07 16:10 UTC (permalink / raw)
  To: Jan Kara; +Cc: Matthew Bobrowski, linux-fsdevel

On Thu, Feb 7, 2019 at 5:18 PM Jan Kara <jack@suse.cz> wrote:
>
> On Thu 10-01-19 19:04:42, Amir Goldstein wrote:
> > When event data type is FSNOTIFY_EVENT_INODE, we don't have a refernece
> > to the mount, so we will not be able to open a file descriptor when user
> > reads the event. However, if the listener has enabled reporting file
> > identifier with the FAN_REPORT_FID init flag, we allow reporting those
> > events and we use an identifier inode to encode fid.
> >
> > The inode to use as identifier when reporting fid depends on the event.
> > For dirent modification events, we report the modified directory inode
> > and we report the "victim" inode otherwise.
> > For example:
> > FS_ATTRIB reports the child inode even if reported on a watched parent.
> > FS_CREATE reports the modified dir inode and not the created inode.
> >
> > Signed-off-by: Amir Goldstein <amir73il@gmail.com>
> > ---
> >  fs/notify/fanotify/fanotify.c      | 67 ++++++++++++++++++++----------
> >  fs/notify/fanotify/fanotify.h      |  2 +-
> >  fs/notify/fanotify/fanotify_user.c |  3 +-
> >  3 files changed, 48 insertions(+), 24 deletions(-)
> >
> > diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c
> > index fcb98ea99508..e3ca1632feb8 100644
> > --- a/fs/notify/fanotify/fanotify.c
> > +++ b/fs/notify/fanotify/fanotify.c
> > @@ -96,7 +96,7 @@ static int fanotify_get_response(struct fsnotify_group *group,
> >
> >       pr_debug("%s: group=%p event=%p about to return ret=%d\n", __func__,
> >                group, event, ret);
> > -
> > +
> >       return ret;
> >  }
> >
> > @@ -106,9 +106,10 @@ static int fanotify_get_response(struct fsnotify_group *group,
> >   * been included within the event mask, but have not been explicitly
> >   * requested by the user, will not be present in the returned mask.
> >   */
> > -static u32 fanotify_group_event_mask(struct fsnotify_iter_info *iter_info,
> > -                                    u32 event_mask, const void *data,
> > -                                    int data_type)
> > +static u32 fanotify_group_event_mask(struct fsnotify_group *group,
> > +                                  struct fsnotify_iter_info *iter_info,
> > +                                  u32 event_mask, const void *data,
> > +                                  int data_type)
> >  {
> >       __u32 marks_mask = 0, marks_ignored_mask = 0;
> >       const struct path *path = data;
> > @@ -118,14 +119,14 @@ static u32 fanotify_group_event_mask(struct fsnotify_iter_info *iter_info,
> >       pr_debug("%s: report_mask=%x mask=%x data=%p data_type=%d\n",
> >                __func__, iter_info->report_mask, event_mask, data, data_type);
> >
> > -     /* If we don't have enough info to send an event to userspace say no */
> > -     if (data_type != FSNOTIFY_EVENT_PATH)
> > -             return 0;
> > -
> > -     /* Sorry, fanotify only gives a damn about files and dirs */
> > -     if (!d_is_reg(path->dentry) &&
> > -         !d_can_lookup(path->dentry))
> > +     if (data_type == FSNOTIFY_EVENT_PATH) {
> > +             /* Path type events are only relevant for files and dirs */
> > +             if (!d_is_reg(path->dentry) && !d_can_lookup(path->dentry))
> > +                     return 0;
>
> Hum, does this mean that fanotify won't report O_PATH open on symlink
> unlike inotify? So shouldn't the condition rather be:
>
>         if (!FAN_GROUP_FLAG(group, FAN_REPORT_FID)) {
>                 if (data_type != FSNOTIFY_EVENT_PATH)
>                         return 0;
>                 if (!d_is_reg(path->dentry) && !d_can_lookup(path->dentry))
>                         return 0;
>         }
>
> ?

Makes sense.

Thanks,
Amir.

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH v5 00/17] fanotify: add support for more event types
  2019-01-10 17:04 [PATCH v5 00/17] fanotify: add support for more event types Amir Goldstein
                   ` (16 preceding siblings ...)
  2019-01-10 17:04 ` [PATCH v5 17/17] fanotify: report FAN_ONDIR to listener with FAN_REPORT_FID Amir Goldstein
@ 2019-02-07 16:26 ` Jan Kara
  17 siblings, 0 replies; 34+ messages in thread
From: Jan Kara @ 2019-02-07 16:26 UTC (permalink / raw)
  To: Amir Goldstein; +Cc: Jan Kara, Matthew Bobrowski, linux-fsdevel, linux-api

Hello,

On Thu 10-01-19 19:04:27, Amir Goldstein wrote:
> This is the 5th revision of patch series to add support for filesystem
> change monitoring to fanotify.
> 
> The complete work is available on fanotify_dirent-v5 branch [1] on github.
> 
> LTP tests by Matthew Bobrowski for FAN_REPORT_FID are available on
> my LTP branch fanotify_fid [2]. A WIP test for dirent events is
> available on my LTP branch fanotify_dirent [3].
> Matthew Bobrowski is working on a proper test for dirent events and on
> man pages for both FAN_REPORT_FID and dirent events (Thanks!).
> 
> The combined functionality of FAN_MARK_FILESYSTEM, FAN_REPORT_FID and
> dirent modification events is demonstrated with a prototype of global
> filesystem monitor based on inotify-tools [4].

OK, I've finally got to reading all the patches and pushing them to my tree
with some small changes. The result is in 'fsnotify' branch in my tree. All
LTP tests (including the new ones) passed so if 0-day does not barf, I'll
push the branch to for_next tomorrow. Thanks for your work!

								Honza

> 
> Thanks,
> Amir.
> 
> Changes since v4:
> - Rebase on v5.0-rc1
> - Address style review comments on v4
> - info_len includes padding to info_hdr alignment
> - handle caching of fsid correctly when inotify marks on object exist
> - Report dirent events on subdirs only with FAN_ONDIR
> - Report XXX_SELF events on directories only with FAN_ONDIR
> - Do not merge dirent events on subdirs with dirent events on non subdirs
> 
> [1] https://github.com/amir73il/linux/commits/fanotify_dirent-v5
> [2] https://github.com/amir73il/ltp/commits/fanotify_fid
> [3] https://github.com/amir73il/ltp/commits/fanotify_dirent
> [4] https://github.com/amir73il/inotify-tools/commits/fanotify_dirent
> 
> Amir Goldstein (17):
>   fsnotify: annotate directory entry modification events
>   fsnotify: remove dirent events from FS_EVENTS_POSS_ON_CHILD mask
>   fsnotify: send all event types to super block marks
>   fsnotify: move mask out of struct fsnotify_event
>   fanotify: rename struct fanotify_{,perm_}event_info
>   fanotify: open code fill_event_metadata()
>   fanotify: encode file identifier for FAN_REPORT_FID
>   fanotify: copy event fid info to user
>   fanotify: enable FAN_REPORT_FID init flag
>   fanotify: cache fsid in fsnotify_mark_connector
>   vfs: add vfs_get_fsid() helper
>   fanotify: use vfs_get_fsid() helper instead of vfs_statfs()
>   fsnotify: report FS_ISDIR flag with MOVE_SELF and DELETE_SELF events
>   fanotify: check FS_ISDIR flag instead of d_is_dir()
>   fanotify: support events with data type FSNOTIFY_EVENT_INODE
>   fanotify: add support for create/attrib/move/delete events
>   fanotify: report FAN_ONDIR to listener with FAN_REPORT_FID
> 
>  fs/notify/fanotify/fanotify.c        | 229 +++++++++++++++++----
>  fs/notify/fanotify/fanotify.h        | 105 ++++++++--
>  fs/notify/fanotify/fanotify_user.c   | 288 +++++++++++++++++++--------
>  fs/notify/fsnotify.c                 |  15 +-
>  fs/notify/inotify/inotify.h          |   1 +
>  fs/notify/inotify/inotify_fsnotify.c |  18 +-
>  fs/notify/inotify/inotify_user.c     |   5 +-
>  fs/notify/mark.c                     |  47 ++++-
>  fs/notify/notification.c             |  22 +-
>  fs/statfs.c                          |  14 ++
>  include/linux/fanotify.h             |  26 ++-
>  include/linux/fsnotify.h             |  94 +++++++--
>  include/linux/fsnotify_backend.h     |  70 ++++---
>  include/linux/statfs.h               |   3 +
>  include/uapi/linux/fanotify.h        |  29 +++
>  15 files changed, 753 insertions(+), 213 deletions(-)
> 
> -- 
> 2.17.1
> 
-- 
Jan Kara <jack@suse.com>
SUSE Labs, CR

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH v5 10/17] fanotify: cache fsid in fsnotify_mark_connector
  2019-02-07 14:48   ` Jan Kara
@ 2019-02-07 16:31     ` Amir Goldstein
  2019-02-08 10:15       ` Jan Kara
  0 siblings, 1 reply; 34+ messages in thread
From: Amir Goldstein @ 2019-02-07 16:31 UTC (permalink / raw)
  To: Jan Kara; +Cc: Matthew Bobrowski, linux-fsdevel

On Thu, Feb 7, 2019 at 4:48 PM Jan Kara <jack@suse.cz> wrote:
>
> On Thu 10-01-19 19:04:37, Amir Goldstein wrote:
> > For FAN_REPORT_FID, we need to encode fid with fsid of the filesystem on
> > every event. To avoid having to call vfs_statfs() on every event to get
> > fsid, we store the fsid in fsnotify_mark_connector on the first time we
> > add a mark and on handle event we use the cached fsid.
> >
> > Subsequent calls to add mark on the same object are expected to pass the
> > same fsid, so the call will fail on cached fsid mismatch.
> >
> > If an event is reported on several mark types (inode, mount, filesystem),
> > all connectors should already have the same fsid, so we use the cached
> > fsid from the first connector.
> >
> > Suggested-by: Jan Kara <jack@suse.cz>
> > Signed-off-by: Amir Goldstein <amir73il@gmail.com>
>
> I've somewhat modified the patch to simplify code flow around
> fanotify_get_fid() and also made fsid argument for
> fsnotify_add_mark_locked() mandatory. The resulting patch is attached.
>

ACK. Two nits.

1. Dan Carpenter reported a smatch warning. Please fix:

fs/notify/fanotify/fanotify.c:194 fanotify_encode_fid() error:
uninitialized symbol 'type'.
fs/notify/fanotify/fanotify.c:194 fanotify_encode_fid() error:
uninitialized symbol 'err'.

2. checkpatch doesn't like cutting long debug strings into 80 chars
(and Greg's linuxsty.vim plugin doesn't warn about them)
referring to the long string that you broke up
pr_warn_ratelimited("%s: fsid mismatch on object of type %u: "...

Thanks,
Amir.

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH v5 10/17] fanotify: cache fsid in fsnotify_mark_connector
  2019-02-07 16:31     ` Amir Goldstein
@ 2019-02-08 10:15       ` Jan Kara
  0 siblings, 0 replies; 34+ messages in thread
From: Jan Kara @ 2019-02-08 10:15 UTC (permalink / raw)
  To: Amir Goldstein; +Cc: Jan Kara, Matthew Bobrowski, linux-fsdevel

On Thu 07-02-19 18:31:19, Amir Goldstein wrote:
> On Thu, Feb 7, 2019 at 4:48 PM Jan Kara <jack@suse.cz> wrote:
> >
> > On Thu 10-01-19 19:04:37, Amir Goldstein wrote:
> > > For FAN_REPORT_FID, we need to encode fid with fsid of the filesystem on
> > > every event. To avoid having to call vfs_statfs() on every event to get
> > > fsid, we store the fsid in fsnotify_mark_connector on the first time we
> > > add a mark and on handle event we use the cached fsid.
> > >
> > > Subsequent calls to add mark on the same object are expected to pass the
> > > same fsid, so the call will fail on cached fsid mismatch.
> > >
> > > If an event is reported on several mark types (inode, mount, filesystem),
> > > all connectors should already have the same fsid, so we use the cached
> > > fsid from the first connector.
> > >
> > > Suggested-by: Jan Kara <jack@suse.cz>
> > > Signed-off-by: Amir Goldstein <amir73il@gmail.com>
> >
> > I've somewhat modified the patch to simplify code flow around
> > fanotify_get_fid() and also made fsid argument for
> > fsnotify_add_mark_locked() mandatory. The resulting patch is attached.
> >
> 
> ACK. Two nits.
> 
> 1. Dan Carpenter reported a smatch warning. Please fix:
> 
> fs/notify/fanotify/fanotify.c:194 fanotify_encode_fid() error:
> uninitialized symbol 'type'.
> fs/notify/fanotify/fanotify.c:194 fanotify_encode_fid() error:
> uninitialized symbol 'err'.

Yes, but this problem went away with my changes as well since we do 'goto
out_err' only after setting err and type.

> 2. checkpatch doesn't like cutting long debug strings into 80 chars
> (and Greg's linuxsty.vim plugin doesn't warn about them)
> referring to the long string that you broke up
> pr_warn_ratelimited("%s: fsid mismatch on object of type %u: "...

I know and I don't take that too seriously. The point is: You don't want to
break the string so that it is easily greppable. But as long as the core
part of the string is in one line, it's OK. In particular once you get to
the part of the format string where you have the format specifiers,
breaking the string is irrelevant for grepping anymore since nobody can
sanely grep that part of the string. And I took care to follow these
guidances.

								Honza
-- 
Jan Kara <jack@suse.com>
SUSE Labs, CR

^ permalink raw reply	[flat|nested] 34+ messages in thread

end of thread, back to index

Thread overview: 34+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-01-10 17:04 [PATCH v5 00/17] fanotify: add support for more event types Amir Goldstein
2019-01-10 17:04 ` [PATCH v5 01/17] fsnotify: annotate directory entry modification events Amir Goldstein
2019-02-06 14:14   ` Jan Kara
2019-01-10 17:04 ` [PATCH v5 02/17] fsnotify: remove dirent events from FS_EVENTS_POSS_ON_CHILD mask Amir Goldstein
2019-01-10 17:04 ` [PATCH v5 03/17] fsnotify: send all event types to super block marks Amir Goldstein
2019-01-10 17:04 ` [PATCH v5 04/17] fsnotify: move mask out of struct fsnotify_event Amir Goldstein
2019-01-10 17:04 ` [PATCH v5 05/17] fanotify: rename struct fanotify_{,perm_}event_info Amir Goldstein
2019-01-10 17:04 ` [PATCH v5 06/17] fanotify: open code fill_event_metadata() Amir Goldstein
2019-01-10 17:04 ` [PATCH v5 07/17] fanotify: encode file identifier for FAN_REPORT_FID Amir Goldstein
2019-01-11  8:10   ` kbuild test robot
2019-01-11  8:37     ` Amir Goldstein
2019-01-18 18:39       ` Paul Burton
2019-01-10 17:04 ` [PATCH v5 08/17] fanotify: copy event fid info to user Amir Goldstein
2019-02-06 17:41   ` Jan Kara
2019-01-10 17:04 ` [PATCH v5 09/17] fanotify: enable FAN_REPORT_FID init flag Amir Goldstein
2019-01-10 17:04 ` [PATCH v5 10/17] fanotify: cache fsid in fsnotify_mark_connector Amir Goldstein
2019-01-11  3:13   ` kbuild test robot
2019-01-14  7:30   ` Dan Carpenter
2019-01-14  7:30     ` Dan Carpenter
2019-01-14  9:17     ` Amir Goldstein
2019-02-07 14:48   ` Jan Kara
2019-02-07 16:31     ` Amir Goldstein
2019-02-08 10:15       ` Jan Kara
2019-01-10 17:04 ` [PATCH v5 11/17] vfs: add vfs_get_fsid() helper Amir Goldstein
2019-01-10 17:04 ` [PATCH v5 12/17] fanotify: use vfs_get_fsid() helper instead of vfs_statfs() Amir Goldstein
2019-01-10 17:04 ` [PATCH v5 13/17] fsnotify: report FS_ISDIR flag with MOVE_SELF and DELETE_SELF events Amir Goldstein
2019-02-07 14:57   ` Jan Kara
2019-01-10 17:04 ` [PATCH v5 14/17] fanotify: check FS_ISDIR flag instead of d_is_dir() Amir Goldstein
2019-01-10 17:04 ` [PATCH v5 15/17] fanotify: support events with data type FSNOTIFY_EVENT_INODE Amir Goldstein
2019-02-07 15:18   ` Jan Kara
2019-02-07 16:10     ` Amir Goldstein
2019-01-10 17:04 ` [PATCH v5 16/17] fanotify: add support for create/attrib/move/delete events Amir Goldstein
2019-01-10 17:04 ` [PATCH v5 17/17] fanotify: report FAN_ONDIR to listener with FAN_REPORT_FID Amir Goldstein
2019-02-07 16:26 ` [PATCH v5 00/17] fanotify: add support for more event types Jan Kara

Linux-Fsdevel Archive on lore.kernel.org

Archives are clonable:
	git clone --mirror https://lore.kernel.org/linux-fsdevel/0 linux-fsdevel/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 linux-fsdevel linux-fsdevel/ https://lore.kernel.org/linux-fsdevel \
		linux-fsdevel@vger.kernel.org linux-fsdevel@archiver.kernel.org
	public-inbox-index linux-fsdevel


Newsgroup available over NNTP:
	nntp://nntp.lore.kernel.org/org.kernel.vger.linux-fsdevel


AGPL code for this site: git clone https://public-inbox.org/ public-inbox