Commit 687c217c authored by Amir Goldstein's avatar Amir Goldstein Committed by Jan Kara
Browse files

fsnotify: pass object pointer and type to fsnotify mark helpers



Instead of passing fsnotify_connp_t, pass the pointer to the marked
object.

Store the object pointer in the connector and move the definition of
fsnotify_connp_t to internal fsnotify subsystem API, so it is no longer
used by fsnotify backends.

Suggested-by: default avatarJan Kara <jack@suse.cz>
Signed-off-by: default avatarAmir Goldstein <amir73il@gmail.com>
Signed-off-by: default avatarJan Kara <jack@suse.cz>
Message-Id: <20240317184154.1200192-6-amir73il@gmail.com>
parent b5cae086
Loading
Loading
Loading
Loading
+20 −75
Original line number Diff line number Diff line
@@ -1076,7 +1076,7 @@ static __u32 fanotify_mark_remove_from_mask(struct fsnotify_mark *fsn_mark,
}

static int fanotify_remove_mark(struct fsnotify_group *group,
				fsnotify_connp_t *connp, __u32 mask,
				void *obj, unsigned int obj_type, __u32 mask,
				unsigned int flags, __u32 umask)
{
	struct fsnotify_mark *fsn_mark = NULL;
@@ -1084,7 +1084,7 @@ static int fanotify_remove_mark(struct fsnotify_group *group,
	int destroy_mark;

	fsnotify_group_lock(group);
	fsn_mark = fsnotify_find_mark(connp, group);
	fsn_mark = fsnotify_find_mark(obj, obj_type, group);
	if (!fsn_mark) {
		fsnotify_group_unlock(group);
		return -ENOENT;
@@ -1105,30 +1105,6 @@ static int fanotify_remove_mark(struct fsnotify_group *group,
	return 0;
}

static int fanotify_remove_vfsmount_mark(struct fsnotify_group *group,
					 struct vfsmount *mnt, __u32 mask,
					 unsigned int flags, __u32 umask)
{
	return fanotify_remove_mark(group, &real_mount(mnt)->mnt_fsnotify_marks,
				    mask, flags, umask);
}

static int fanotify_remove_sb_mark(struct fsnotify_group *group,
				   struct super_block *sb, __u32 mask,
				   unsigned int flags, __u32 umask)
{
	return fanotify_remove_mark(group, &sb->s_fsnotify_marks, mask,
				    flags, umask);
}

static int fanotify_remove_inode_mark(struct fsnotify_group *group,
				      struct inode *inode, __u32 mask,
				      unsigned int flags, __u32 umask)
{
	return fanotify_remove_mark(group, &inode->i_fsnotify_marks, mask,
				    flags, umask);
}

static bool fanotify_mark_update_flags(struct fsnotify_mark *fsn_mark,
				       unsigned int fan_flags)
{
@@ -1249,7 +1225,7 @@ static int fanotify_set_mark_fsid(struct fsnotify_group *group,
}

static struct fsnotify_mark *fanotify_add_new_mark(struct fsnotify_group *group,
						   fsnotify_connp_t *connp,
						   void *obj,
						   unsigned int obj_type,
						   unsigned int fan_flags,
						   struct fan_fsid *fsid)
@@ -1288,7 +1264,7 @@ static struct fsnotify_mark *fanotify_add_new_mark(struct fsnotify_group *group,
		fan_mark->fsid.val[0] = fan_mark->fsid.val[1] = 0;
	}

	ret = fsnotify_add_mark_locked(mark, connp, obj_type, 0);
	ret = fsnotify_add_mark_locked(mark, obj, obj_type, 0);
	if (ret)
		goto out_put_mark;

@@ -1344,7 +1320,7 @@ static int fanotify_may_update_existing_mark(struct fsnotify_mark *fsn_mark,
}

static int fanotify_add_mark(struct fsnotify_group *group,
			     fsnotify_connp_t *connp, unsigned int obj_type,
			     void *obj, unsigned int obj_type,
			     __u32 mask, unsigned int fan_flags,
			     struct fan_fsid *fsid)
{
@@ -1353,9 +1329,9 @@ static int fanotify_add_mark(struct fsnotify_group *group,
	int ret = 0;

	fsnotify_group_lock(group);
	fsn_mark = fsnotify_find_mark(connp, group);
	fsn_mark = fsnotify_find_mark(obj, obj_type, group);
	if (!fsn_mark) {
		fsn_mark = fanotify_add_new_mark(group, connp, obj_type,
		fsn_mark = fanotify_add_new_mark(group, obj, obj_type,
						 fan_flags, fsid);
		if (IS_ERR(fsn_mark)) {
			fsnotify_group_unlock(group);
@@ -1392,30 +1368,6 @@ static int fanotify_add_mark(struct fsnotify_group *group,
	return ret;
}

static int fanotify_add_vfsmount_mark(struct fsnotify_group *group,
				      struct vfsmount *mnt, __u32 mask,
				      unsigned int flags, struct fan_fsid *fsid)
{
	return fanotify_add_mark(group, &real_mount(mnt)->mnt_fsnotify_marks,
				 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 fan_fsid *fsid)
{
	return fanotify_add_mark(group, &sb->s_fsnotify_marks,
				 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, struct fan_fsid *fsid)
{
	return fanotify_add_mark(group, &inode->i_fsnotify_marks,
				 FSNOTIFY_OBJ_TYPE_INODE, mask, flags, fsid);
}

static struct fsnotify_event *fanotify_alloc_overflow_event(void)
{
	struct fanotify_event *oevent;
@@ -1738,6 +1690,7 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask,
	unsigned int mark_cmd = flags & FANOTIFY_MARK_CMD_BITS;
	unsigned int ignore = flags & FANOTIFY_MARK_IGNORE_BITS;
	unsigned int obj_type, fid_mode;
	void *obj;
	u32 umask = 0;
	int ret;

@@ -1896,10 +1849,16 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask,
	}

	/* inode held in place by reference to path; group by fget on fd */
	if (mark_type == FAN_MARK_INODE)
	if (mark_type == FAN_MARK_INODE) {
		inode = path.dentry->d_inode;
	else
		obj = inode;
	} else {
		mnt = path.mnt;
		if (mark_type == FAN_MARK_MOUNT)
			obj = mnt;
		else
			obj = mnt->mnt_sb;
	}

	/*
	 * If some other task has this inode open for write we should not add
@@ -1935,26 +1894,12 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask,
	/* create/update an inode mark */
	switch (mark_cmd) {
	case FAN_MARK_ADD:
		if (mark_type == FAN_MARK_MOUNT)
			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, fsid);
		else
			ret = fanotify_add_inode_mark(group, inode, mask,
						      flags, fsid);
		ret = fanotify_add_mark(group, obj, obj_type, mask, flags,
					fsid);
		break;
	case FAN_MARK_REMOVE:
		if (mark_type == FAN_MARK_MOUNT)
			ret = fanotify_remove_vfsmount_mark(group, mnt, mask,
							    flags, umask);
		else if (mark_type == FAN_MARK_FILESYSTEM)
			ret = fanotify_remove_sb_mark(group, mnt->mnt_sb, mask,
						      flags, umask);
		else
			ret = fanotify_remove_inode_mark(group, inode, mask,
							 flags, umask);
		ret = fanotify_remove_mark(group, obj, obj_type, mask, flags,
					   umask);
		break;
	default:
		ret = -EINVAL;
+10 −13
Original line number Diff line number Diff line
@@ -9,22 +9,28 @@

#include "../mount.h"

/*
 * fsnotify_connp_t is what we embed in objects which connector can be attached
 * to.
 */
typedef struct fsnotify_mark_connector __rcu *fsnotify_connp_t;

static inline struct inode *fsnotify_conn_inode(
				struct fsnotify_mark_connector *conn)
{
	return container_of(conn->obj, struct inode, i_fsnotify_marks);
	return conn->obj;
}

static inline struct mount *fsnotify_conn_mount(
				struct fsnotify_mark_connector *conn)
{
	return container_of(conn->obj, struct mount, mnt_fsnotify_marks);
	return real_mount(conn->obj);
}

static inline struct super_block *fsnotify_conn_sb(
				struct fsnotify_mark_connector *conn)
{
	return container_of(conn->obj, struct super_block, s_fsnotify_marks);
	return conn->obj;
}

static inline struct super_block *fsnotify_object_sb(void *obj,
@@ -45,16 +51,7 @@ static inline struct super_block *fsnotify_object_sb(void *obj,
static inline struct super_block *fsnotify_connector_sb(
				struct fsnotify_mark_connector *conn)
{
	switch (conn->type) {
	case FSNOTIFY_OBJ_TYPE_INODE:
		return fsnotify_conn_inode(conn)->i_sb;
	case FSNOTIFY_OBJ_TYPE_VFSMOUNT:
		return fsnotify_conn_mount(conn)->mnt.mnt_sb;
	case FSNOTIFY_OBJ_TYPE_SB:
		return fsnotify_conn_sb(conn);
	default:
		return NULL;
	}
	return fsnotify_object_sb(conn->obj, conn->type);
}

/* destroy all events sitting in this groups notification queue */
+17 −11
Original line number Diff line number Diff line
@@ -265,6 +265,7 @@ static void *fsnotify_detach_connector_from_object(
					struct fsnotify_mark_connector *conn,
					unsigned int *type)
{
	fsnotify_connp_t *connp = fsnotify_object_connp(conn->obj, conn->type);
	struct inode *inode = NULL;

	*type = conn->type;
@@ -285,7 +286,7 @@ static void *fsnotify_detach_connector_from_object(
	}

	fsnotify_put_sb_watchers(conn);
	rcu_assign_pointer(*(conn->obj), NULL);
	rcu_assign_pointer(*connp, NULL);
	conn->obj = NULL;
	conn->type = FSNOTIFY_OBJ_TYPE_DETACHED;

@@ -560,7 +561,7 @@ 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 obj_type)
					       void *obj, unsigned int obj_type)
{
	struct fsnotify_mark_connector *conn;

@@ -571,7 +572,7 @@ static int fsnotify_attach_connector_to_object(fsnotify_connp_t *connp,
	INIT_HLIST_HEAD(&conn->list);
	conn->flags = 0;
	conn->type = obj_type;
	conn->obj = connp;
	conn->obj = obj;

	/*
	 * cmpxchg() provides the barrier so that readers of *connp can see
@@ -620,24 +621,25 @@ static struct fsnotify_mark_connector *fsnotify_grab_connector(
 * to which group and for which inodes. These marks are ordered according to
 * priority, highest number first, and then by the group's location in memory.
 */
static int fsnotify_add_mark_list(struct fsnotify_mark *mark,
				  fsnotify_connp_t *connp,
static int fsnotify_add_mark_list(struct fsnotify_mark *mark, void *obj,
				  unsigned int obj_type, int add_flags)
{
	struct fsnotify_mark *lmark, *last = NULL;
	struct fsnotify_mark_connector *conn;
	fsnotify_connp_t *connp;
	int cmp;
	int err = 0;

	if (WARN_ON(!fsnotify_valid_obj_type(obj_type)))
		return -EINVAL;

	connp = fsnotify_object_connp(obj, obj_type);
restart:
	spin_lock(&mark->lock);
	conn = fsnotify_grab_connector(connp);
	if (!conn) {
		spin_unlock(&mark->lock);
		err = fsnotify_attach_connector_to_object(connp, obj_type);
		err = fsnotify_attach_connector_to_object(connp, obj, obj_type);
		if (err)
			return err;
		goto restart;
@@ -689,7 +691,7 @@ static int fsnotify_add_mark_list(struct fsnotify_mark *mark,
 * event types should be delivered to which group.
 */
int fsnotify_add_mark_locked(struct fsnotify_mark *mark,
			     fsnotify_connp_t *connp, unsigned int obj_type,
			     void *obj, unsigned int obj_type,
			     int add_flags)
{
	struct fsnotify_group *group = mark->group;
@@ -710,7 +712,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, obj_type, add_flags);
	ret = fsnotify_add_mark_list(mark, obj, obj_type, add_flags);
	if (ret)
		goto err;

@@ -728,14 +730,14 @@ int fsnotify_add_mark_locked(struct fsnotify_mark *mark,
	return ret;
}

int fsnotify_add_mark(struct fsnotify_mark *mark, fsnotify_connp_t *connp,
int fsnotify_add_mark(struct fsnotify_mark *mark, void *obj,
		      unsigned int obj_type, int add_flags)
{
	int ret;
	struct fsnotify_group *group = mark->group;

	fsnotify_group_lock(group);
	ret = fsnotify_add_mark_locked(mark, connp, obj_type, add_flags);
	ret = fsnotify_add_mark_locked(mark, obj, obj_type, add_flags);
	fsnotify_group_unlock(group);
	return ret;
}
@@ -745,12 +747,16 @@ EXPORT_SYMBOL_GPL(fsnotify_add_mark);
 * Given a list of marks, find the mark associated with given group. If found
 * take a reference to that mark and return it, else return NULL.
 */
struct fsnotify_mark *fsnotify_find_mark(fsnotify_connp_t *connp,
struct fsnotify_mark *fsnotify_find_mark(void *obj, unsigned int obj_type,
					 struct fsnotify_group *group)
{
	fsnotify_connp_t *connp = fsnotify_object_connp(obj, obj_type);
	struct fsnotify_mark_connector *conn;
	struct fsnotify_mark *mark;

	if (!connp)
		return NULL;

	conn = fsnotify_grab_connector(connp);
	if (!conn)
		return NULL;
+12 −21
Original line number Diff line number Diff line
@@ -456,13 +456,6 @@ FSNOTIFY_ITER_FUNCS(sb, SB)
	     type < FSNOTIFY_ITER_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/sb point to this structure which tracks all marks attached to
 * the inode/vfsmount/sb. The reference to inode/vfsmount/sb is held by this
@@ -476,7 +469,7 @@ struct fsnotify_mark_connector {
	unsigned short flags;	/* flags [lock] */
	union {
		/* Object pointer [lock] */
		fsnotify_connp_t *obj;
		void *obj;
		/* Used listing heads to free after srcu period expires */
		struct fsnotify_mark_connector *destroy_next;
	};
@@ -763,14 +756,12 @@ 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(fsnotify_connp_t *connp,
struct fsnotify_mark *fsnotify_find_mark(void *obj, unsigned int obj_type,
					 struct fsnotify_group *group);
/* attach the mark to the object */
extern int fsnotify_add_mark(struct fsnotify_mark *mark,
			     fsnotify_connp_t *connp, unsigned int obj_type,
			     int add_flags);
extern int fsnotify_add_mark_locked(struct fsnotify_mark *mark,
				    fsnotify_connp_t *connp,
int fsnotify_add_mark(struct fsnotify_mark *mark, void *obj,
		      unsigned int obj_type, int add_flags);
int fsnotify_add_mark_locked(struct fsnotify_mark *mark, void *obj,
			     unsigned int obj_type, int add_flags);

/* attach the mark to the inode */
@@ -778,22 +769,22 @@ static inline int fsnotify_add_inode_mark(struct fsnotify_mark *mark,
					  struct inode *inode,
					  int add_flags)
{
	return fsnotify_add_mark(mark, &inode->i_fsnotify_marks,
				 FSNOTIFY_OBJ_TYPE_INODE, add_flags);
	return fsnotify_add_mark(mark, inode, FSNOTIFY_OBJ_TYPE_INODE,
				 add_flags);
}
static inline int fsnotify_add_inode_mark_locked(struct fsnotify_mark *mark,
						 struct inode *inode,
						 int add_flags)
{
	return fsnotify_add_mark_locked(mark, &inode->i_fsnotify_marks,
					FSNOTIFY_OBJ_TYPE_INODE, add_flags);
	return fsnotify_add_mark_locked(mark, inode, FSNOTIFY_OBJ_TYPE_INODE,
					add_flags);
}

static inline struct fsnotify_mark *fsnotify_find_inode_mark(
						struct inode *inode,
						struct fsnotify_group *group)
{
	return fsnotify_find_mark(&inode->i_fsnotify_marks, group);
	return fsnotify_find_mark(inode, FSNOTIFY_OBJ_TYPE_INODE, group);
}

/* given a group and a mark, flag mark to be freed when all references are dropped */