diff mbox series

[v3,1/2] Add fanotify_get_supported_init_flags() helper function

Message ID 20231020150749.21165-2-mdoucha@suse.cz
State Accepted
Headers show
Series Fix fanotify14 | expand

Commit Message

Martin Doucha Oct. 20, 2023, 3:06 p.m. UTC
Since FAN_ALL_INIT_FLAGS constant is deprecated, the kernel has added
new fanotify feature flags and there is no other way to check
for their support, we need to manually check which init flags needed
by our tests are available.

Signed-off-by: Martin Doucha <mdoucha@suse.cz>
---

Changes since v1:
- Fixed check for FAN_REPORT_NAME
- Added longer patch description

Changes since v2:
- Added a table of flag dependencies so that each individual flag is tested
  together with all additional required flags

The helper function also checks that it wasn't called with a new uknown
flag which might require dependency table update. In that case, the test
will fail and advise the developer to review documentation and update
the dependency table.

 testcases/kernel/syscalls/fanotify/fanotify.h | 43 +++++++++++++++++++
 1 file changed, 43 insertions(+)

Comments

Amir Goldstein Oct. 20, 2023, 3:55 p.m. UTC | #1
On Fri, Oct 20, 2023 at 6:07 PM Martin Doucha <mdoucha@suse.cz> wrote:
>
> Since FAN_ALL_INIT_FLAGS constant is deprecated, the kernel has added
> new fanotify feature flags and there is no other way to check
> for their support, we need to manually check which init flags needed
> by our tests are available.
>
> Signed-off-by: Martin Doucha <mdoucha@suse.cz>
> ---
>
> Changes since v1:
> - Fixed check for FAN_REPORT_NAME
> - Added longer patch description
>
> Changes since v2:
> - Added a table of flag dependencies so that each individual flag is tested
>   together with all additional required flags
>
> The helper function also checks that it wasn't called with a new uknown
> flag which might require dependency table update. In that case, the test
> will fail and advise the developer to review documentation and update
> the dependency table.
>

This is much more sane than the previous version :)
You may add:

Reviewed-by: Amir Goldstein <amir73il@gmail.com>

>  testcases/kernel/syscalls/fanotify/fanotify.h | 43 +++++++++++++++++++
>  1 file changed, 43 insertions(+)
>
> diff --git a/testcases/kernel/syscalls/fanotify/fanotify.h b/testcases/kernel/syscalls/fanotify/fanotify.h
> index 75a081dc9..78424a350 100644
> --- a/testcases/kernel/syscalls/fanotify/fanotify.h
> +++ b/testcases/kernel/syscalls/fanotify/fanotify.h
> @@ -217,6 +217,49 @@ static inline int fanotify_init_flags_supported_by_kernel(unsigned int flags)
>         return fanotify_init_flags_supported_on_fs(flags, NULL);
>  }
>
> +#define TST_FANOTIFY_INIT_KNOWN_FLAGS                                      \
> +       (FAN_REPORT_DFID_NAME_TARGET | FAN_REPORT_TID | FAN_REPORT_PIDFD | \
> +       FAN_CLASS_NOTIF | FAN_CLASS_CONTENT | FAN_CLASS_PRE_CONTENT)
> +
> +/*
> + * Check support of given init flags one by one and return those which are
> + * supported.
> + */
> +static inline unsigned int fanotify_get_supported_init_flags(unsigned int flags,
> +       const char *fname)
> +{
> +       unsigned int i, flg, arg, ret = 0;
> +       static const struct { unsigned int flag, deps; } deplist[] = {
> +               {FAN_REPORT_NAME, FAN_REPORT_DIR_FID},
> +               {FAN_REPORT_TARGET_FID, FAN_REPORT_DFID_NAME_FID},
> +               {0, 0}
> +       };
> +
> +       if (flags & ~TST_FANOTIFY_INIT_KNOWN_FLAGS) {
> +               tst_brk(TBROK, "fanotify_init() feature check called with unknown flags %x, please update flag dependency table if needed",
> +                       flags & ~TST_FANOTIFY_INIT_KNOWN_FLAGS);
> +       }
> +
> +       for (flg = 1; flg; flg <<= 1) {
> +               if (!(flags & flg))
> +                       continue;
> +
> +               arg = flg;
> +
> +               for (i = 0; deplist[i].flag; i++) {
> +                       if (deplist[i].flag == flg) {
> +                               arg |= deplist[i].deps;
> +                               break;
> +                       }
> +               }
> +
> +               if (!fanotify_init_flags_supported_on_fs(arg, fname))
> +                       ret |= flg;
> +       }
> +
> +       return ret;
> +}
> +
>  typedef void (*tst_res_func_t)(const char *file, const int lineno,
>                                int ttype, const char *fmt, ...);
>
> --
> 2.42.0
>
Petr Vorel Oct. 23, 2023, 12:50 p.m. UTC | #2
Hi Martin, Amir,

Reviewed-by: Petr Vorel <pvorel@suse.cz>

Kind regards,
Petr
diff mbox series

Patch

diff --git a/testcases/kernel/syscalls/fanotify/fanotify.h b/testcases/kernel/syscalls/fanotify/fanotify.h
index 75a081dc9..78424a350 100644
--- a/testcases/kernel/syscalls/fanotify/fanotify.h
+++ b/testcases/kernel/syscalls/fanotify/fanotify.h
@@ -217,6 +217,49 @@  static inline int fanotify_init_flags_supported_by_kernel(unsigned int flags)
 	return fanotify_init_flags_supported_on_fs(flags, NULL);
 }
 
+#define TST_FANOTIFY_INIT_KNOWN_FLAGS                                      \
+	(FAN_REPORT_DFID_NAME_TARGET | FAN_REPORT_TID | FAN_REPORT_PIDFD | \
+	FAN_CLASS_NOTIF | FAN_CLASS_CONTENT | FAN_CLASS_PRE_CONTENT)
+
+/*
+ * Check support of given init flags one by one and return those which are
+ * supported.
+ */
+static inline unsigned int fanotify_get_supported_init_flags(unsigned int flags,
+	const char *fname)
+{
+	unsigned int i, flg, arg, ret = 0;
+	static const struct { unsigned int flag, deps; } deplist[] = {
+		{FAN_REPORT_NAME, FAN_REPORT_DIR_FID},
+		{FAN_REPORT_TARGET_FID, FAN_REPORT_DFID_NAME_FID},
+		{0, 0}
+	};
+
+	if (flags & ~TST_FANOTIFY_INIT_KNOWN_FLAGS) {
+		tst_brk(TBROK, "fanotify_init() feature check called with unknown flags %x, please update flag dependency table if needed",
+			flags & ~TST_FANOTIFY_INIT_KNOWN_FLAGS);
+	}
+
+	for (flg = 1; flg; flg <<= 1) {
+		if (!(flags & flg))
+			continue;
+
+		arg = flg;
+
+		for (i = 0; deplist[i].flag; i++) {
+			if (deplist[i].flag == flg) {
+				arg |= deplist[i].deps;
+				break;
+			}
+		}
+
+		if (!fanotify_init_flags_supported_on_fs(arg, fname))
+			ret |= flg;
+	}
+
+	return ret;
+}
+
 typedef void (*tst_res_func_t)(const char *file, const int lineno,
 			       int ttype, const char *fmt, ...);