Commit 734a1a5e authored by Gabriel Krisman Bertazi's avatar Gabriel Krisman Bertazi Committed by Jan Kara
Browse files

fanotify: Pre-allocate pool of error events

Pre-allocate slots for file system errors to have greater chances of
succeeding, since error events can happen in GFP_NOFS context.  This
patch introduces a group-wide mempool of error events, shared by all
FAN_FS_ERROR marks in this group.

Link: https://lore.kernel.org/r/20211025192746.66445-20-krisman@collabora.com


Reviewed-by: default avatarAmir Goldstein <amir73il@gmail.com>
Reviewed-by: default avatarJan Kara <jack@suse.cz>
Signed-off-by: default avatarGabriel Krisman Bertazi <krisman@collabora.com>
Signed-off-by: default avatarJan Kara <jack@suse.cz>
parent 8d11a4f4
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -819,6 +819,9 @@ static void fanotify_free_group_priv(struct fsnotify_group *group)
	if (group->fanotify_data.ucounts)
		dec_ucount(group->fanotify_data.ucounts,
			   UCOUNT_FANOTIFY_GROUPS);

	if (mempool_initialized(&group->fanotify_data.error_events_pool))
		mempool_exit(&group->fanotify_data.error_events_pool);
}

static void fanotify_free_path_event(struct fanotify_event *event)
+11 −0
Original line number Diff line number Diff line
@@ -141,6 +141,7 @@ enum fanotify_event_type {
	FANOTIFY_EVENT_TYPE_PATH,
	FANOTIFY_EVENT_TYPE_PATH_PERM,
	FANOTIFY_EVENT_TYPE_OVERFLOW, /* struct fanotify_event */
	FANOTIFY_EVENT_TYPE_FS_ERROR, /* struct fanotify_error_event */
	__FANOTIFY_EVENT_TYPE_NUM
};

@@ -196,6 +197,16 @@ FANOTIFY_NE(struct fanotify_event *event)
	return container_of(event, struct fanotify_name_event, fae);
}

struct fanotify_error_event {
	struct fanotify_event fae;
};

static inline struct fanotify_error_event *
FANOTIFY_EE(struct fanotify_event *event)
{
	return container_of(event, struct fanotify_error_event, fae);
}

static inline __kernel_fsid_t *fanotify_event_fsid(struct fanotify_event *event)
{
	if (event->type == FANOTIFY_EVENT_TYPE_FID)
+25 −1
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@
#define FANOTIFY_DEFAULT_MAX_EVENTS	16384
#define FANOTIFY_OLD_DEFAULT_MAX_MARKS	8192
#define FANOTIFY_DEFAULT_MAX_GROUPS	128
#define FANOTIFY_DEFAULT_FEE_POOL_SIZE	32

/*
 * Legacy fanotify marks limits (8192) is per group and we introduced a tunable
@@ -1054,6 +1055,15 @@ static struct fsnotify_mark *fanotify_add_new_mark(struct fsnotify_group *group,
	return ERR_PTR(ret);
}

static int fanotify_group_init_error_pool(struct fsnotify_group *group)
{
	if (mempool_initialized(&group->fanotify_data.error_events_pool))
		return 0;

	return mempool_init_kmalloc_pool(&group->fanotify_data.error_events_pool,
					 FANOTIFY_DEFAULT_FEE_POOL_SIZE,
					 sizeof(struct fanotify_error_event));
}

static int fanotify_add_mark(struct fsnotify_group *group,
			     fsnotify_connp_t *connp, unsigned int type,
@@ -1062,6 +1072,7 @@ static int fanotify_add_mark(struct fsnotify_group *group,
{
	struct fsnotify_mark *fsn_mark;
	__u32 added;
	int ret = 0;

	mutex_lock(&group->mark_mutex);
	fsn_mark = fsnotify_find_mark(connp, group);
@@ -1072,13 +1083,26 @@ static int fanotify_add_mark(struct fsnotify_group *group,
			return PTR_ERR(fsn_mark);
		}
	}

	/*
	 * Error events are pre-allocated per group, only if strictly
	 * needed (i.e. FAN_FS_ERROR was requested).
	 */
	if (!(flags & FAN_MARK_IGNORED_MASK) && (mask & FAN_FS_ERROR)) {
		ret = fanotify_group_init_error_pool(group);
		if (ret)
			goto out;
	}

	added = fanotify_mark_add_to_mask(fsn_mark, mask, flags);
	if (added & ~fsnotify_conn_mask(fsn_mark->connector))
		fsnotify_recalc_mask(fsn_mark->connector);

out:
	mutex_unlock(&group->mark_mutex);

	fsnotify_put_mark(fsn_mark);
	return 0;
	return ret;
}

static int fanotify_add_vfsmount_mark(struct fsnotify_group *group,
+2 −0
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@
#include <linux/atomic.h>
#include <linux/user_namespace.h>
#include <linux/refcount.h>
#include <linux/mempool.h>

/*
 * IN_* from inotfy.h lines up EXACTLY with FS_*, this is so we can easily
@@ -246,6 +247,7 @@ struct fsnotify_group {
			int flags;           /* flags from fanotify_init() */
			int f_flags; /* event_f_flags from fanotify_init() */
			struct ucounts *ucounts;
			mempool_t error_events_pool;
		} fanotify_data;
#endif /* CONFIG_FANOTIFY */
	};