From 9b6e543450dc03635899ba56b1c39cc593694560 Mon Sep 17 00:00:00 2001 From: Amir Goldstein Date: Sat, 23 Jun 2018 17:54:47 +0300 Subject: fsnotify: use typedef fsnotify_connp_t for brevity The object marks manipulation functions fsnotify_destroy_marks() fsnotify_find_mark() and their helpers take an argument of type struct fsnotify_mark_connector __rcu ** to dereference the connector pointer. use a typedef to describe this type for brevity. Signed-off-by: Amir Goldstein Signed-off-by: Jan Kara --- include/linux/fsnotify_backend.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'include/linux') diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h index b38964a7a521..e7cd7fc6e3cf 100644 --- a/include/linux/fsnotify_backend.h +++ b/include/linux/fsnotify_backend.h @@ -268,6 +268,8 @@ struct fsnotify_mark_connector { struct hlist_head list; }; +typedef struct fsnotify_mark_connector __rcu *fsnotify_connp_t; + /* * A mark is simply an object attached to an in core inode which allows an * fsnotify listener to indicate they are either no longer interested in events @@ -394,9 +396,8 @@ extern void fsnotify_recalc_mask(struct fsnotify_mark_connector *conn); extern void fsnotify_init_mark(struct fsnotify_mark *mark, struct fsnotify_group *group); /* Find mark belonging to given group in the list of marks */ -extern struct fsnotify_mark *fsnotify_find_mark( - struct fsnotify_mark_connector __rcu **connp, - struct fsnotify_group *group); +extern struct fsnotify_mark *fsnotify_find_mark(fsnotify_connp_t *connp, + struct fsnotify_group *group); /* attach the mark to the inode or vfsmount */ extern int fsnotify_add_mark(struct fsnotify_mark *mark, struct inode *inode, struct vfsmount *mnt, int allow_dups); -- cgit v1.2.3 From b812a9f5896379b6cff2ac168ddb5b89037d8e78 Mon Sep 17 00:00:00 2001 From: Amir Goldstein Date: Sat, 23 Jun 2018 17:54:48 +0300 Subject: fsnotify: pass connp and object type to fsnotify_add_mark() Instead of passing inode and vfsmount arguments to fsnotify_add_mark() and its _locked variant, pass an abstract object pointer and the object type. The helpers fsnotify_obj_{inode,mount} are added to get the concrete object pointer from abstract object pointer. Signed-off-by: Amir Goldstein Signed-off-by: Jan Kara --- include/linux/fsnotify_backend.h | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) (limited to 'include/linux') diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h index e7cd7fc6e3cf..8efb8663453d 100644 --- a/include/linux/fsnotify_backend.h +++ b/include/linux/fsnotify_backend.h @@ -210,6 +210,11 @@ enum fsnotify_obj_type { #define FSNOTIFY_OBJ_TYPE_VFSMOUNT_FL (1U << FSNOTIFY_OBJ_TYPE_VFSMOUNT) #define FSNOTIFY_OBJ_ALL_TYPES_MASK ((1U << FSNOTIFY_OBJ_TYPE_COUNT) - 1) +static inline bool fsnotify_valid_obj_type(unsigned int type) +{ + return (type < FSNOTIFY_OBJ_TYPE_COUNT); +} + struct fsnotify_iter_info { struct fsnotify_mark *marks[FSNOTIFY_OBJ_TYPE_COUNT]; unsigned int report_mask; @@ -398,24 +403,27 @@ 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); -/* attach the mark to the inode or vfsmount */ -extern int fsnotify_add_mark(struct fsnotify_mark *mark, struct inode *inode, - struct vfsmount *mnt, int allow_dups); +/* 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, - struct inode *inode, struct vfsmount *mnt, + fsnotify_connp_t *connp, unsigned int type, int allow_dups); /* 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, NULL, allow_dups); + return fsnotify_add_mark(mark, &inode->i_fsnotify_marks, + FSNOTIFY_OBJ_TYPE_INODE, allow_dups); } 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, NULL, allow_dups); + 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, -- cgit v1.2.3 From 36f10f55ff1d2867bfc48ed898a9cc0dc6b49dd2 Mon Sep 17 00:00:00 2001 From: Amir Goldstein Date: Sat, 23 Jun 2018 17:54:49 +0300 Subject: fsnotify: let connector point to an abstract object Make the code to attach/detach a connector to object more generic by letting the fsnotify connector point to an abstract fsnotify_connp_t. Code that needs to dereference an inode or mount object now uses the helpers fsnotify_conn_{inode,mount}. Signed-off-by: Amir Goldstein Signed-off-by: Jan Kara --- include/linux/fsnotify_backend.h | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'include/linux') diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h index 8efb8663453d..381cfb0e67fa 100644 --- a/include/linux/fsnotify_backend.h +++ b/include/linux/fsnotify_backend.h @@ -255,6 +255,13 @@ FSNOTIFY_ITER_FUNCS(vfsmount, VFSMOUNT) #define fsnotify_foreach_obj_type(type) \ for (type = 0; type < FSNOTIFY_OBJ_TYPE_COUNT; type++) +/* + * fsnotify_connp_t is what we embed in objects which connector can be attached + * to. fsnotify_connp_t * is how we refer from connector back to object. + */ +struct fsnotify_mark_connector; +typedef struct fsnotify_mark_connector __rcu *fsnotify_connp_t; + /* * Inode / vfsmount point to this structure which tracks all marks attached to * the inode / vfsmount. The reference to inode / vfsmount is held by this @@ -264,17 +271,15 @@ FSNOTIFY_ITER_FUNCS(vfsmount, VFSMOUNT) struct fsnotify_mark_connector { spinlock_t lock; unsigned int type; /* Type of object [lock] */ - union { /* Object pointer [lock] */ - struct inode *inode; - struct vfsmount *mnt; + union { + /* Object pointer [lock] */ + fsnotify_connp_t *obj; /* Used listing heads to free after srcu period expires */ struct fsnotify_mark_connector *destroy_next; }; struct hlist_head list; }; -typedef struct fsnotify_mark_connector __rcu *fsnotify_connp_t; - /* * A mark is simply an object attached to an in core inode which allows an * fsnotify listener to indicate they are either no longer interested in events -- cgit v1.2.3 From 3ac70bfcde812b1b97d8a88a832df59941fa293f Mon Sep 17 00:00:00 2001 From: Amir Goldstein Date: Sat, 23 Jun 2018 17:54:50 +0300 Subject: fsnotify: add helper to get mask from connector Use a helper to get the mask from the object (i.e. i_fsnotify_mask) to generalize code of add/remove inode/vfsmount mark. Signed-off-by: Amir Goldstein Signed-off-by: Jan Kara --- include/linux/fsnotify_backend.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'include/linux') diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h index 381cfb0e67fa..2b9b6f1ff5e0 100644 --- a/include/linux/fsnotify_backend.h +++ b/include/linux/fsnotify_backend.h @@ -401,6 +401,8 @@ extern struct fsnotify_event *fsnotify_remove_first_event(struct fsnotify_group /* functions used to manipulate the marks attached to inodes */ +/* Get mask of events for a list of marks */ +extern __u32 fsnotify_conn_mask(struct fsnotify_mark_connector *conn); /* Calculate mask of events for a list of marks */ extern void fsnotify_recalc_mask(struct fsnotify_mark_connector *conn); extern void fsnotify_init_mark(struct fsnotify_mark *mark, -- cgit v1.2.3 From 4d97f7d53da7dc830dbf416a3d2a6778d267ae68 Mon Sep 17 00:00:00 2001 From: Henry Wilson Date: Thu, 31 May 2018 09:43:03 +0000 Subject: inotify: Add flag IN_MASK_CREATE for inotify_add_watch() The flag IN_MASK_CREATE is introduced as a flag for inotiy_add_watch() which prevents inotify from modifying any existing watches when invoked. If the pathname specified in the call has a watched inode associated with it and IN_MASK_CREATE is specified, fail with an errno of EEXIST. Use of IN_MASK_CREATE with IN_MASK_ADD is reserved for future use and will return EINVAL. RATIONALE In the current implementation, there is no way to prevent inotify_add_watch() from modifying existing watch descriptors. Even if the caller keeps a record of all watch descriptors collected, this is only sufficient to detect that an existing watch descriptor may have been modified. The assumption that a particular path will map to the same inode over multiple calls to inotify_add_watch() cannot be made as files can be renamed or deleted. It is also not possible to assume that two distinct paths do no map to the same inode, due to hard-links or a dereferenced symbolic link. Further uses of inotify_add_watch() to revert the change may cause other watch descriptors to be modified or created, merely compunding the problem. There is currently no system call such as inotify_modify_watch() to explicity modify a watch descriptor, which would be able to revert unwanted changes. Thus the caller cannot guarantee to be able to revert any changes to existing watch decriptors. Additionally the caller cannot assume that the events that are associated with a watch descriptor are within the set requested, as any future calls to inotify_add_watch() may unintentionally modify a watch descriptor's mask. Thus it cannot currently be guaranteed that a watch descriptor will only generate events which have been requested. The program must filter events which come through its watch descriptor to within its expected range. Reviewed-by: Amir Goldstein Signed-off-by: Henry Wilson Signed-off-by: Jan Kara --- include/linux/inotify.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include/linux') diff --git a/include/linux/inotify.h b/include/linux/inotify.h index 44f9ffe72c87..6a24905f6e1e 100644 --- a/include/linux/inotify.h +++ b/include/linux/inotify.h @@ -18,6 +18,6 @@ extern struct ctl_table inotify_table[]; /* for sysctl */ IN_DELETE_SELF | IN_MOVE_SELF | IN_UNMOUNT | \ IN_Q_OVERFLOW | IN_IGNORED | IN_ONLYDIR | \ IN_DONT_FOLLOW | IN_EXCL_UNLINK | IN_MASK_ADD | \ - IN_ISDIR | IN_ONESHOT) + IN_MASK_CREATE | IN_ISDIR | IN_ONESHOT) #endif /* _LINUX_INOTIFY_H */ -- cgit v1.2.3