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

fsnotify: create helper fsnotify_update_sb_watchers()



We would like to count watched objects by priority group, so we will need
to update the watched object counter after adding/removing marks.

Create a helper fsnotify_update_sb_watchers() and call it after
attaching/detaching a mark, instead of fsnotify_{get,put}_sb_watchers()
only after attaching/detaching a connector.

Soon, we will use this helper to count watched objects by the highest
watching priority group.

Signed-off-by: default avatarAmir Goldstein <amir73il@gmail.com>
Signed-off-by: default avatarJan Kara <jack@suse.cz>
Message-Id: <20240317184154.1200192-7-amir73il@gmail.com>
parent 687c217c
Loading
Loading
Loading
Loading
+22 −14
Original line number Diff line number Diff line
@@ -154,21 +154,24 @@ static void fsnotify_put_inode_ref(struct inode *inode)
	iput(inode);
}

static void fsnotify_get_sb_watchers(struct fsnotify_mark_connector *conn)
/*
 * Grab or drop watched objects reference depending on whether the connector
 * is attached and has any marks attached.
 */
static void fsnotify_update_sb_watchers(struct super_block *sb,
					struct fsnotify_mark_connector *conn)
{
	struct super_block *sb = fsnotify_connector_sb(conn);
	bool is_watched = conn->flags & FSNOTIFY_CONN_FLAG_IS_WATCHED;
	bool has_marks = conn->obj && !hlist_empty(&conn->list);

	if (sb)
	if (has_marks && !is_watched) {
		conn->flags |= FSNOTIFY_CONN_FLAG_IS_WATCHED;
		fsnotify_get_sb_watched_objects(sb);
}

static void fsnotify_put_sb_watchers(struct fsnotify_mark_connector *conn)
{
	struct super_block *sb = fsnotify_connector_sb(conn);

	if (sb)
	} else if (!has_marks && is_watched) {
		conn->flags &= ~FSNOTIFY_CONN_FLAG_IS_WATCHED;
		fsnotify_put_sb_watched_objects(sb);
	}
}

/*
 * Grab or drop inode reference for the connector if needed.
@@ -266,6 +269,7 @@ static void *fsnotify_detach_connector_from_object(
					unsigned int *type)
{
	fsnotify_connp_t *connp = fsnotify_object_connp(conn->obj, conn->type);
	struct super_block *sb = fsnotify_connector_sb(conn);
	struct inode *inode = NULL;

	*type = conn->type;
@@ -285,10 +289,10 @@ static void *fsnotify_detach_connector_from_object(
		fsnotify_conn_sb(conn)->s_fsnotify_mask = 0;
	}

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

	return inode;
}
@@ -340,6 +344,11 @@ void fsnotify_put_mark(struct fsnotify_mark *mark)
		objp = fsnotify_detach_connector_from_object(conn, &type);
		free_conn = true;
	} else {
		struct super_block *sb = fsnotify_connector_sb(conn);

		/* Update watched objects after detaching mark */
		if (sb)
			fsnotify_update_sb_watchers(sb, conn);
		objp = __fsnotify_recalc_mask(conn);
		type = conn->type;
	}
@@ -581,10 +590,7 @@ static int fsnotify_attach_connector_to_object(fsnotify_connp_t *connp,
	if (cmpxchg(connp, NULL, conn)) {
		/* Someone else created list structure for us */
		kmem_cache_free(fsnotify_mark_connector_cachep, conn);
		return 0;
	}

	fsnotify_get_sb_watchers(conn);
	return 0;
}

@@ -624,6 +630,7 @@ static struct fsnotify_mark_connector *fsnotify_grab_connector(
static int fsnotify_add_mark_list(struct fsnotify_mark *mark, void *obj,
				  unsigned int obj_type, int add_flags)
{
	struct super_block *sb = fsnotify_object_sb(obj, obj_type);
	struct fsnotify_mark *lmark, *last = NULL;
	struct fsnotify_mark_connector *conn;
	fsnotify_connp_t *connp;
@@ -673,6 +680,7 @@ static int fsnotify_add_mark_list(struct fsnotify_mark *mark, void *obj,
	/* mark should be the last entry.  last is the current last entry */
	hlist_add_behind_rcu(&mark->obj_list, &last->obj_list);
added:
	fsnotify_update_sb_watchers(sb, conn);
	/*
	 * Since connector is attached to object using cmpxchg() we are
	 * guaranteed that connector initialization is fully visible by anyone
+1 −0
Original line number Diff line number Diff line
@@ -465,6 +465,7 @@ FSNOTIFY_ITER_FUNCS(sb, SB)
struct fsnotify_mark_connector {
	spinlock_t lock;
	unsigned short type;	/* Type of object [lock] */
#define FSNOTIFY_CONN_FLAG_IS_WATCHED	0x01
#define FSNOTIFY_CONN_FLAG_HAS_IREF	0x02
	unsigned short flags;	/* flags [lock] */
	union {