mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	fsnotify: Pass fsnotify_iter_info into handle_event handler
Pass fsnotify_iter_info into ->handle_event() handler so that it can release and reacquire SRCU lock via fsnotify_prepare_user_wait() and fsnotify_finish_user_wait() functions. These functions also make sure current marks are appropriately pinned so that iteration protected by srcu in fsnotify() stays safe. Reviewed-by: Miklos Szeredi <mszeredi@redhat.com> Reviewed-by: Amir Goldstein <amir73il@gmail.com> Signed-off-by: Jan Kara <jack@suse.cz>
This commit is contained in:
		
							parent
							
								
									abc77577a6
								
							
						
					
					
						commit
						9385a84d7e
					
				
					 10 changed files with 30 additions and 15 deletions
				
			
		| 
						 | 
				
			
			@ -85,7 +85,8 @@ static int dnotify_handle_event(struct fsnotify_group *group,
 | 
			
		|||
				struct fsnotify_mark *inode_mark,
 | 
			
		||||
				struct fsnotify_mark *vfsmount_mark,
 | 
			
		||||
				u32 mask, const void *data, int data_type,
 | 
			
		||||
				const unsigned char *file_name, u32 cookie)
 | 
			
		||||
				const unsigned char *file_name, u32 cookie,
 | 
			
		||||
				struct fsnotify_iter_info *iter_info)
 | 
			
		||||
{
 | 
			
		||||
	struct dnotify_mark *dn_mark;
 | 
			
		||||
	struct dnotify_struct *dn;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -174,7 +174,8 @@ static int fanotify_handle_event(struct fsnotify_group *group,
 | 
			
		|||
				 struct fsnotify_mark *inode_mark,
 | 
			
		||||
				 struct fsnotify_mark *fanotify_mark,
 | 
			
		||||
				 u32 mask, const void *data, int data_type,
 | 
			
		||||
				 const unsigned char *file_name, u32 cookie)
 | 
			
		||||
				 const unsigned char *file_name, u32 cookie,
 | 
			
		||||
				 struct fsnotify_iter_info *iter_info)
 | 
			
		||||
{
 | 
			
		||||
	int ret = 0;
 | 
			
		||||
	struct fanotify_event_info *event;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -127,7 +127,8 @@ static int send_to_group(struct inode *to_tell,
 | 
			
		|||
			 struct fsnotify_mark *vfsmount_mark,
 | 
			
		||||
			 __u32 mask, const void *data,
 | 
			
		||||
			 int data_is, u32 cookie,
 | 
			
		||||
			 const unsigned char *file_name)
 | 
			
		||||
			 const unsigned char *file_name,
 | 
			
		||||
			 struct fsnotify_iter_info *iter_info)
 | 
			
		||||
{
 | 
			
		||||
	struct fsnotify_group *group = NULL;
 | 
			
		||||
	__u32 inode_test_mask = 0;
 | 
			
		||||
| 
						 | 
				
			
			@ -178,7 +179,7 @@ static int send_to_group(struct inode *to_tell,
 | 
			
		|||
 | 
			
		||||
	return group->ops->handle_event(group, to_tell, inode_mark,
 | 
			
		||||
					vfsmount_mark, mask, data, data_is,
 | 
			
		||||
					file_name, cookie);
 | 
			
		||||
					file_name, cookie, iter_info);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
| 
						 | 
				
			
			@ -194,8 +195,9 @@ int fsnotify(struct inode *to_tell, __u32 mask, const void *data, int data_is,
 | 
			
		|||
	struct fsnotify_mark *inode_mark = NULL, *vfsmount_mark = NULL;
 | 
			
		||||
	struct fsnotify_group *inode_group, *vfsmount_group;
 | 
			
		||||
	struct fsnotify_mark_connector *inode_conn, *vfsmount_conn;
 | 
			
		||||
	struct fsnotify_iter_info iter_info;
 | 
			
		||||
	struct mount *mnt;
 | 
			
		||||
	int idx, ret = 0;
 | 
			
		||||
	int ret = 0;
 | 
			
		||||
	/* global tests shouldn't care about events on child only the specific event */
 | 
			
		||||
	__u32 test_mask = (mask & ~FS_EVENT_ON_CHILD);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -224,7 +226,7 @@ int fsnotify(struct inode *to_tell, __u32 mask, const void *data, int data_is,
 | 
			
		|||
	    !(mnt && test_mask & mnt->mnt_fsnotify_mask))
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	idx = srcu_read_lock(&fsnotify_mark_srcu);
 | 
			
		||||
	iter_info.srcu_idx = srcu_read_lock(&fsnotify_mark_srcu);
 | 
			
		||||
 | 
			
		||||
	if ((mask & FS_MODIFY) ||
 | 
			
		||||
	    (test_mask & to_tell->i_fsnotify_mask)) {
 | 
			
		||||
| 
						 | 
				
			
			@ -284,8 +286,13 @@ int fsnotify(struct inode *to_tell, __u32 mask, const void *data, int data_is,
 | 
			
		|||
				vfsmount_mark = NULL;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		iter_info.inode_mark = inode_mark;
 | 
			
		||||
		iter_info.vfsmount_mark = vfsmount_mark;
 | 
			
		||||
 | 
			
		||||
		ret = send_to_group(to_tell, inode_mark, vfsmount_mark, mask,
 | 
			
		||||
				    data, data_is, cookie, file_name);
 | 
			
		||||
				    data, data_is, cookie, file_name,
 | 
			
		||||
				    &iter_info);
 | 
			
		||||
 | 
			
		||||
		if (ret && (mask & ALL_FSNOTIFY_PERM_EVENTS))
 | 
			
		||||
			goto out;
 | 
			
		||||
| 
						 | 
				
			
			@ -299,7 +306,7 @@ int fsnotify(struct inode *to_tell, __u32 mask, const void *data, int data_is,
 | 
			
		|||
	}
 | 
			
		||||
	ret = 0;
 | 
			
		||||
out:
 | 
			
		||||
	srcu_read_unlock(&fsnotify_mark_srcu, idx);
 | 
			
		||||
	srcu_read_unlock(&fsnotify_mark_srcu, iter_info.srcu_idx);
 | 
			
		||||
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -27,7 +27,8 @@ extern int inotify_handle_event(struct fsnotify_group *group,
 | 
			
		|||
				struct fsnotify_mark *inode_mark,
 | 
			
		||||
				struct fsnotify_mark *vfsmount_mark,
 | 
			
		||||
				u32 mask, const void *data, int data_type,
 | 
			
		||||
				const unsigned char *file_name, u32 cookie);
 | 
			
		||||
				const unsigned char *file_name, u32 cookie,
 | 
			
		||||
				struct fsnotify_iter_info *iter_info);
 | 
			
		||||
 | 
			
		||||
extern const struct fsnotify_ops inotify_fsnotify_ops;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -68,7 +68,8 @@ int inotify_handle_event(struct fsnotify_group *group,
 | 
			
		|||
			 struct fsnotify_mark *inode_mark,
 | 
			
		||||
			 struct fsnotify_mark *vfsmount_mark,
 | 
			
		||||
			 u32 mask, const void *data, int data_type,
 | 
			
		||||
			 const unsigned char *file_name, u32 cookie)
 | 
			
		||||
			 const unsigned char *file_name, u32 cookie,
 | 
			
		||||
			 struct fsnotify_iter_info *iter_info)
 | 
			
		||||
{
 | 
			
		||||
	struct inotify_inode_mark *i_mark;
 | 
			
		||||
	struct inotify_event_info *event;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -474,7 +474,7 @@ void inotify_ignored_and_remove_idr(struct fsnotify_mark *fsn_mark,
 | 
			
		|||
 | 
			
		||||
	/* Queue ignore event for the watch */
 | 
			
		||||
	inotify_handle_event(group, NULL, fsn_mark, NULL, FS_IN_IGNORED,
 | 
			
		||||
			     NULL, FSNOTIFY_EVENT_NONE, NULL, 0);
 | 
			
		||||
			     NULL, FSNOTIFY_EVENT_NONE, NULL, 0, NULL);
 | 
			
		||||
 | 
			
		||||
	i_mark = container_of(fsn_mark, struct inotify_inode_mark, fsn_mark);
 | 
			
		||||
	/* remove this mark from the idr */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -99,7 +99,8 @@ struct fsnotify_ops {
 | 
			
		|||
			    struct fsnotify_mark *inode_mark,
 | 
			
		||||
			    struct fsnotify_mark *vfsmount_mark,
 | 
			
		||||
			    u32 mask, const void *data, int data_type,
 | 
			
		||||
			    const unsigned char *file_name, u32 cookie);
 | 
			
		||||
			    const unsigned char *file_name, u32 cookie,
 | 
			
		||||
			    struct fsnotify_iter_info *iter_info);
 | 
			
		||||
	void (*free_group_priv)(struct fsnotify_group *group);
 | 
			
		||||
	void (*freeing_mark)(struct fsnotify_mark *mark, struct fsnotify_group *group);
 | 
			
		||||
	void (*free_event)(struct fsnotify_event *event);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -168,7 +168,8 @@ static int audit_mark_handle_event(struct fsnotify_group *group,
 | 
			
		|||
				    struct fsnotify_mark *inode_mark,
 | 
			
		||||
				    struct fsnotify_mark *vfsmount_mark,
 | 
			
		||||
				    u32 mask, const void *data, int data_type,
 | 
			
		||||
				    const unsigned char *dname, u32 cookie)
 | 
			
		||||
				    const unsigned char *dname, u32 cookie,
 | 
			
		||||
				    struct fsnotify_iter_info *iter_info)
 | 
			
		||||
{
 | 
			
		||||
	struct audit_fsnotify_mark *audit_mark;
 | 
			
		||||
	const struct inode *inode = NULL;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -989,7 +989,8 @@ static int audit_tree_handle_event(struct fsnotify_group *group,
 | 
			
		|||
				   struct fsnotify_mark *inode_mark,
 | 
			
		||||
				   struct fsnotify_mark *vfsmount_mark,
 | 
			
		||||
				   u32 mask, const void *data, int data_type,
 | 
			
		||||
				   const unsigned char *file_name, u32 cookie)
 | 
			
		||||
				   const unsigned char *file_name, u32 cookie,
 | 
			
		||||
				   struct fsnotify_iter_info *iter_info)
 | 
			
		||||
{
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -472,7 +472,8 @@ static int audit_watch_handle_event(struct fsnotify_group *group,
 | 
			
		|||
				    struct fsnotify_mark *inode_mark,
 | 
			
		||||
				    struct fsnotify_mark *vfsmount_mark,
 | 
			
		||||
				    u32 mask, const void *data, int data_type,
 | 
			
		||||
				    const unsigned char *dname, u32 cookie)
 | 
			
		||||
				    const unsigned char *dname, u32 cookie,
 | 
			
		||||
				    struct fsnotify_iter_info *iter_info)
 | 
			
		||||
{
 | 
			
		||||
	const struct inode *inode;
 | 
			
		||||
	struct audit_parent *parent;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue