diff mbox series

[4/4] syscalls/fanotify09: Add test cases for merge of ignore mask

Message ID 20220620132737.2015073-5-amir73il@gmail.com
State Accepted
Headers show
Series More fanotify tests for v5.19 | expand

Commit Message

Amir Goldstein June 20, 2022, 1:27 p.m. UTC
1. Verify that an ignore mask that does not survive modify event,
   does survive a modify event on child, if parent is not watching
   events on children.

2. Verify that an ignore mask on parent does not ignore close events
   sent to mount mark, if parent is not watching events on children.

The behavior of these corner cases of ignore mask on parent dir have
always been undefined, so do not run the test for kernel < v5.19.

Signed-off-by: Amir Goldstein <amir73il@gmail.com>
---
 .../kernel/syscalls/fanotify/fanotify09.c     | 72 +++++++++++++++++--
 1 file changed, 68 insertions(+), 4 deletions(-)

Comments

Jan Kara June 20, 2022, 3:20 p.m. UTC | #1
On Mon 20-06-22 16:27:37, Amir Goldstein wrote:
> 1. Verify that an ignore mask that does not survive modify event,
>    does survive a modify event on child, if parent is not watching
>    events on children.
> 
> 2. Verify that an ignore mask on parent does not ignore close events
>    sent to mount mark, if parent is not watching events on children.
> 
> The behavior of these corner cases of ignore mask on parent dir have
> always been undefined, so do not run the test for kernel < v5.19.
> 
> Signed-off-by: Amir Goldstein <amir73il@gmail.com>

Hum, I was looking into the testcase. What does generate a modify event
there and checks that ignore mask does not survive it?

								Honza

> ---
>  .../kernel/syscalls/fanotify/fanotify09.c     | 72 +++++++++++++++++--
>  1 file changed, 68 insertions(+), 4 deletions(-)
> 
> diff --git a/testcases/kernel/syscalls/fanotify/fanotify09.c b/testcases/kernel/syscalls/fanotify/fanotify09.c
> index 070ad9933..0eb83e2f8 100644
> --- a/testcases/kernel/syscalls/fanotify/fanotify09.c
> +++ b/testcases/kernel/syscalls/fanotify/fanotify09.c
> @@ -27,6 +27,11 @@
>   * Test case #5 is a regression test for commit:
>   *
>   *      7372e79c9eb9 fanotify: fix logic of reporting name info with watched parent
> + *
> + * Test cases #6-#7 are regression tests for commit:
> + * (from v5.19, unlikely to be backported thus not in .tags):
> + *
> + *      e730558adffb fanotify: consistent behavior for parent not watching children
>   */
>  
>  #define _GNU_SOURCE
> @@ -73,6 +78,7 @@ static struct tcase {
>  	const char *tname;
>  	struct fanotify_mark_type mark;
>  	unsigned int ondir;
> +	unsigned int ignore;
>  	unsigned int report_name;
>  	const char *close_nowrite;
>  	int nevents;
> @@ -83,6 +89,7 @@ static struct tcase {
>  		INIT_FANOTIFY_MARK_TYPE(MOUNT),
>  		0,
>  		0,
> +		0,
>  		DIR_NAME,
>  		1, 0,
>  	},
> @@ -91,6 +98,7 @@ static struct tcase {
>  		INIT_FANOTIFY_MARK_TYPE(MOUNT),
>  		FAN_ONDIR,
>  		0,
> +		0,
>  		DIR_NAME,
>  		2, 0,
>  	},
> @@ -99,6 +107,7 @@ static struct tcase {
>  		INIT_FANOTIFY_MARK_TYPE(MOUNT),
>  		FAN_ONDIR,
>  		0,
> +		0,
>  		".",
>  		2, 0
>  	},
> @@ -107,6 +116,7 @@ static struct tcase {
>  		INIT_FANOTIFY_MARK_TYPE(INODE),
>  		FAN_ONDIR,
>  		0,
> +		0,
>  		DIR_NAME,
>  		2, 0,
>  	},
> @@ -115,6 +125,7 @@ static struct tcase {
>  		INIT_FANOTIFY_MARK_TYPE(MOUNT),
>  		0,
>  		0,
> +		0,
>  		FILE2_NAME,
>  		2, FAN_CLOSE_NOWRITE,
>  	},
> @@ -122,10 +133,29 @@ static struct tcase {
>  		"Events on non-dir child with both parent and mount marks and filename info",
>  		INIT_FANOTIFY_MARK_TYPE(MOUNT),
>  		0,
> +		0,
>  		FAN_REPORT_DFID_NAME,
>  		FILE2_NAME,
>  		2, FAN_CLOSE_NOWRITE,
>  	},
> +	{
> +		"Events on non-dir child with ignore mask on parent",
> +		INIT_FANOTIFY_MARK_TYPE(MOUNT),
> +		0,
> +		FAN_MARK_IGNORED_MASK,
> +		0,
> +		DIR_NAME,
> +		1, 0,
> +	},
> +	{
> +		"Events on non-dir children with surviving ignore mask on parent",
> +		INIT_FANOTIFY_MARK_TYPE(MOUNT),
> +		0,
> +		FAN_MARK_IGNORED_MASK | FAN_MARK_IGNORED_SURV_MODIFY,
> +		0,
> +		FILE2_NAME,
> +		2, FAN_CLOSE_NOWRITE,
> +	},
>  };
>  
>  static void create_fanotify_groups(struct tcase *tc)
> @@ -140,13 +170,14 @@ static void create_fanotify_groups(struct tcase *tc)
>  		 */
>  		unsigned int report_name = tc->report_name;
>  		unsigned int mask_flags = tc->ondir | FAN_EVENT_ON_CHILD;
> -		unsigned int parent_mask;
> +		unsigned int parent_mask, ignore = 0;
>  
>  		/*
>  		 * The non-first groups do not request events on children and
> -		 * subdirs.
> +		 * subdirs and may set an ignore mask on parent dir.
>  		 */
>  		if (i > 0) {
> +			ignore = tc->ignore;
>  			report_name = 0;
>  			mask_flags = 0;
>  		}
> @@ -168,10 +199,15 @@ static void create_fanotify_groups(struct tcase *tc)
>  		 * but only the first group requests events on child.
>  		 * The one mark with FAN_EVENT_ON_CHILD is needed for
>  		 * setting the DCACHE_FSNOTIFY_PARENT_WATCHED dentry flag.
> +		 *
> +		 * The inode mark on non-first group is either with FAN_MODIFY
> +		 * in mask or FAN_CLOSE_NOWRITE in ignore mask. In either case,
> +		 * it is not expected to get the modify event on a child, nor
> +		 * the close event on dir.
>  		 */
>  		parent_mask = FAN_MODIFY | tc->ondir | mask_flags;
> -		SAFE_FANOTIFY_MARK(fd_notify[i], FAN_MARK_ADD,
> -				    parent_mask,
> +		SAFE_FANOTIFY_MARK(fd_notify[i], FAN_MARK_ADD | ignore,
> +				    ignore ? FAN_CLOSE_NOWRITE : parent_mask,
>  				    AT_FDCWD, ".");
>  	}
>  }
> @@ -186,6 +222,21 @@ static void cleanup_fanotify_groups(void)
>  	}
>  }
>  
> +static void check_ignore_mask(int fd)
> +{
> +	unsigned int ignored_mask, mflags;
> +	char procfdinfo[100];
> +
> +	sprintf(procfdinfo, "/proc/%d/fdinfo/%d", (int)getpid(), fd);
> +	if (FILE_LINES_SCANF(procfdinfo, "fanotify ino:%*x sdev:%*x mflags: %x mask:0 ignored_mask:%x",
> +				&mflags, &ignored_mask) || !ignored_mask) {
> +		tst_res(TFAIL, "The ignore mask did not survive");
> +	} else {
> +		tst_res(TPASS, "Found mark with ignore mask (ignored_mask=%x, mflags=%x) in %s",
> +				ignored_mask, mflags, procfdinfo);
> +	}
> +}
> +
>  static void event_res(int ttype, int group,
>  		      struct fanotify_event_metadata *event,
>  		      const char *filename)
> @@ -274,6 +325,12 @@ static void test_fanotify(unsigned int n)
>  		return;
>  	}
>  
> +	if (tc->ignore && tst_kvercmp(5, 19, 0) < 0) {
> +		tst_res(TCONF, "ignored mask on parent dir has undefined "
> +				"behavior on kernel < 5.19");
> +		return;
> +	}
> +
>  	create_fanotify_groups(tc);
>  
>  	/*
> @@ -326,6 +383,13 @@ static void test_fanotify(unsigned int n)
>  	 * got the FAN_CLOSE_NOWRITE event only on a non-directory.
>  	 */
>  	for (i = 1; i < NUM_GROUPS; i++) {
> +		/*
> +		 * Verify that ignore mask survived the modify event on child,
> +		 * which was not supposed to be sent to this group.
> +		 */
> +		if (tc->ignore)
> +			check_ignore_mask(fd_notify[i]);
> +
>  		ret = read(fd_notify[i], event_buf, EVENT_BUF_LEN);
>  		if (ret > 0) {
>  			event = (struct fanotify_event_metadata *)event_buf;
> -- 
> 2.25.1
>
Amir Goldstein June 20, 2022, 4:59 p.m. UTC | #2
On Mon, Jun 20, 2022 at 6:20 PM Jan Kara <jack@suse.cz> wrote:
>
> On Mon 20-06-22 16:27:37, Amir Goldstein wrote:
> > 1. Verify that an ignore mask that does not survive modify event,
> >    does survive a modify event on child, if parent is not watching
> >    events on children.
> >
> > 2. Verify that an ignore mask on parent does not ignore close events
> >    sent to mount mark, if parent is not watching events on children.
> >
> > The behavior of these corner cases of ignore mask on parent dir have
> > always been undefined, so do not run the test for kernel < v5.19.
> >
> > Signed-off-by: Amir Goldstein <amir73il@gmail.com>
>
> Hum, I was looking into the testcase. What does generate a modify event
> there and checks that ignore mask does not survive it?

I think this does:

        /*
         * generate MODIFY event and no FAN_CLOSE_NOWRITE event.
         */
        SAFE_FILE_PRINTF(fname, "1");

Thanks,
Amir.
Jan Kara June 20, 2022, 8:35 p.m. UTC | #3
On Mon 20-06-22 19:59:48, Amir Goldstein wrote:
> On Mon, Jun 20, 2022 at 6:20 PM Jan Kara <jack@suse.cz> wrote:
> >
> > On Mon 20-06-22 16:27:37, Amir Goldstein wrote:
> > > 1. Verify that an ignore mask that does not survive modify event,
> > >    does survive a modify event on child, if parent is not watching
> > >    events on children.
> > >
> > > 2. Verify that an ignore mask on parent does not ignore close events
> > >    sent to mount mark, if parent is not watching events on children.
> > >
> > > The behavior of these corner cases of ignore mask on parent dir have
> > > always been undefined, so do not run the test for kernel < v5.19.
> > >
> > > Signed-off-by: Amir Goldstein <amir73il@gmail.com>
> >
> > Hum, I was looking into the testcase. What does generate a modify event
> > there and checks that ignore mask does not survive it?
> 
> I think this does:
> 
>         /*
>          * generate MODIFY event and no FAN_CLOSE_NOWRITE event.
>          */
>         SAFE_FILE_PRINTF(fname, "1");

Yeah, I was looking at that but then I'm somewhat confused because this
gets called in .setup() hook while the notification groups get created only
in .test() hook that gets called later. What am I missing?

								Honza
Amir Goldstein June 21, 2022, 3:02 a.m. UTC | #4
On Mon, Jun 20, 2022 at 11:35 PM Jan Kara <jack@suse.cz> wrote:
>
> On Mon 20-06-22 19:59:48, Amir Goldstein wrote:
> > On Mon, Jun 20, 2022 at 6:20 PM Jan Kara <jack@suse.cz> wrote:
> > >
> > > On Mon 20-06-22 16:27:37, Amir Goldstein wrote:
> > > > 1. Verify that an ignore mask that does not survive modify event,
> > > >    does survive a modify event on child, if parent is not watching
> > > >    events on children.
> > > >
> > > > 2. Verify that an ignore mask on parent does not ignore close events
> > > >    sent to mount mark, if parent is not watching events on children.
> > > >
> > > > The behavior of these corner cases of ignore mask on parent dir have
> > > > always been undefined, so do not run the test for kernel < v5.19.
> > > >
> > > > Signed-off-by: Amir Goldstein <amir73il@gmail.com>
> > >
> > > Hum, I was looking into the testcase. What does generate a modify event
> > > there and checks that ignore mask does not survive it?
> >
> > I think this does:
> >
> >         /*
> >          * generate MODIFY event and no FAN_CLOSE_NOWRITE event.
> >          */
> >         SAFE_FILE_PRINTF(fname, "1");
>
> Yeah, I was looking at that but then I'm somewhat confused because this
> gets called in .setup() hook while the notification groups get created only
> in .test() hook that gets called later. What am I missing?

There is one in setup().
The one with the comment above is from test_fanotify().

Thanks,
Amir.
Jan Kara June 21, 2022, 8:31 a.m. UTC | #5
On Tue 21-06-22 06:02:24, Amir Goldstein wrote:
> On Mon, Jun 20, 2022 at 11:35 PM Jan Kara <jack@suse.cz> wrote:
> >
> > On Mon 20-06-22 19:59:48, Amir Goldstein wrote:
> > > On Mon, Jun 20, 2022 at 6:20 PM Jan Kara <jack@suse.cz> wrote:
> > > >
> > > > On Mon 20-06-22 16:27:37, Amir Goldstein wrote:
> > > > > 1. Verify that an ignore mask that does not survive modify event,
> > > > >    does survive a modify event on child, if parent is not watching
> > > > >    events on children.
> > > > >
> > > > > 2. Verify that an ignore mask on parent does not ignore close events
> > > > >    sent to mount mark, if parent is not watching events on children.
> > > > >
> > > > > The behavior of these corner cases of ignore mask on parent dir have
> > > > > always been undefined, so do not run the test for kernel < v5.19.
> > > > >
> > > > > Signed-off-by: Amir Goldstein <amir73il@gmail.com>
> > > >
> > > > Hum, I was looking into the testcase. What does generate a modify event
> > > > there and checks that ignore mask does not survive it?
> > >
> > > I think this does:
> > >
> > >         /*
> > >          * generate MODIFY event and no FAN_CLOSE_NOWRITE event.
> > >          */
> > >         SAFE_FILE_PRINTF(fname, "1");
> >
> > Yeah, I was looking at that but then I'm somewhat confused because this
> > gets called in .setup() hook while the notification groups get created only
> > in .test() hook that gets called later. What am I missing?
> 
> There is one in setup().
> The one with the comment above is from test_fanotify().

Bah, I must have been blind... Thanks for directing me.

								Honza
Jan Kara June 21, 2022, 8:34 a.m. UTC | #6
On Mon 20-06-22 16:27:37, Amir Goldstein wrote:
> 1. Verify that an ignore mask that does not survive modify event,
>    does survive a modify event on child, if parent is not watching
>    events on children.
> 
> 2. Verify that an ignore mask on parent does not ignore close events
>    sent to mount mark, if parent is not watching events on children.
> 
> The behavior of these corner cases of ignore mask on parent dir have
> always been undefined, so do not run the test for kernel < v5.19.
> 
> Signed-off-by: Amir Goldstein <amir73il@gmail.com>

OK, after Amir cleared my confusing things looks good to me. Feel free to
add:

Reviewed-by: Jan Kara <jack@suse.cz>

								Honza

> ---
>  .../kernel/syscalls/fanotify/fanotify09.c     | 72 +++++++++++++++++--
>  1 file changed, 68 insertions(+), 4 deletions(-)
> 
> diff --git a/testcases/kernel/syscalls/fanotify/fanotify09.c b/testcases/kernel/syscalls/fanotify/fanotify09.c
> index 070ad9933..0eb83e2f8 100644
> --- a/testcases/kernel/syscalls/fanotify/fanotify09.c
> +++ b/testcases/kernel/syscalls/fanotify/fanotify09.c
> @@ -27,6 +27,11 @@
>   * Test case #5 is a regression test for commit:
>   *
>   *      7372e79c9eb9 fanotify: fix logic of reporting name info with watched parent
> + *
> + * Test cases #6-#7 are regression tests for commit:
> + * (from v5.19, unlikely to be backported thus not in .tags):
> + *
> + *      e730558adffb fanotify: consistent behavior for parent not watching children
>   */
>  
>  #define _GNU_SOURCE
> @@ -73,6 +78,7 @@ static struct tcase {
>  	const char *tname;
>  	struct fanotify_mark_type mark;
>  	unsigned int ondir;
> +	unsigned int ignore;
>  	unsigned int report_name;
>  	const char *close_nowrite;
>  	int nevents;
> @@ -83,6 +89,7 @@ static struct tcase {
>  		INIT_FANOTIFY_MARK_TYPE(MOUNT),
>  		0,
>  		0,
> +		0,
>  		DIR_NAME,
>  		1, 0,
>  	},
> @@ -91,6 +98,7 @@ static struct tcase {
>  		INIT_FANOTIFY_MARK_TYPE(MOUNT),
>  		FAN_ONDIR,
>  		0,
> +		0,
>  		DIR_NAME,
>  		2, 0,
>  	},
> @@ -99,6 +107,7 @@ static struct tcase {
>  		INIT_FANOTIFY_MARK_TYPE(MOUNT),
>  		FAN_ONDIR,
>  		0,
> +		0,
>  		".",
>  		2, 0
>  	},
> @@ -107,6 +116,7 @@ static struct tcase {
>  		INIT_FANOTIFY_MARK_TYPE(INODE),
>  		FAN_ONDIR,
>  		0,
> +		0,
>  		DIR_NAME,
>  		2, 0,
>  	},
> @@ -115,6 +125,7 @@ static struct tcase {
>  		INIT_FANOTIFY_MARK_TYPE(MOUNT),
>  		0,
>  		0,
> +		0,
>  		FILE2_NAME,
>  		2, FAN_CLOSE_NOWRITE,
>  	},
> @@ -122,10 +133,29 @@ static struct tcase {
>  		"Events on non-dir child with both parent and mount marks and filename info",
>  		INIT_FANOTIFY_MARK_TYPE(MOUNT),
>  		0,
> +		0,
>  		FAN_REPORT_DFID_NAME,
>  		FILE2_NAME,
>  		2, FAN_CLOSE_NOWRITE,
>  	},
> +	{
> +		"Events on non-dir child with ignore mask on parent",
> +		INIT_FANOTIFY_MARK_TYPE(MOUNT),
> +		0,
> +		FAN_MARK_IGNORED_MASK,
> +		0,
> +		DIR_NAME,
> +		1, 0,
> +	},
> +	{
> +		"Events on non-dir children with surviving ignore mask on parent",
> +		INIT_FANOTIFY_MARK_TYPE(MOUNT),
> +		0,
> +		FAN_MARK_IGNORED_MASK | FAN_MARK_IGNORED_SURV_MODIFY,
> +		0,
> +		FILE2_NAME,
> +		2, FAN_CLOSE_NOWRITE,
> +	},
>  };
>  
>  static void create_fanotify_groups(struct tcase *tc)
> @@ -140,13 +170,14 @@ static void create_fanotify_groups(struct tcase *tc)
>  		 */
>  		unsigned int report_name = tc->report_name;
>  		unsigned int mask_flags = tc->ondir | FAN_EVENT_ON_CHILD;
> -		unsigned int parent_mask;
> +		unsigned int parent_mask, ignore = 0;
>  
>  		/*
>  		 * The non-first groups do not request events on children and
> -		 * subdirs.
> +		 * subdirs and may set an ignore mask on parent dir.
>  		 */
>  		if (i > 0) {
> +			ignore = tc->ignore;
>  			report_name = 0;
>  			mask_flags = 0;
>  		}
> @@ -168,10 +199,15 @@ static void create_fanotify_groups(struct tcase *tc)
>  		 * but only the first group requests events on child.
>  		 * The one mark with FAN_EVENT_ON_CHILD is needed for
>  		 * setting the DCACHE_FSNOTIFY_PARENT_WATCHED dentry flag.
> +		 *
> +		 * The inode mark on non-first group is either with FAN_MODIFY
> +		 * in mask or FAN_CLOSE_NOWRITE in ignore mask. In either case,
> +		 * it is not expected to get the modify event on a child, nor
> +		 * the close event on dir.
>  		 */
>  		parent_mask = FAN_MODIFY | tc->ondir | mask_flags;
> -		SAFE_FANOTIFY_MARK(fd_notify[i], FAN_MARK_ADD,
> -				    parent_mask,
> +		SAFE_FANOTIFY_MARK(fd_notify[i], FAN_MARK_ADD | ignore,
> +				    ignore ? FAN_CLOSE_NOWRITE : parent_mask,
>  				    AT_FDCWD, ".");
>  	}
>  }
> @@ -186,6 +222,21 @@ static void cleanup_fanotify_groups(void)
>  	}
>  }
>  
> +static void check_ignore_mask(int fd)
> +{
> +	unsigned int ignored_mask, mflags;
> +	char procfdinfo[100];
> +
> +	sprintf(procfdinfo, "/proc/%d/fdinfo/%d", (int)getpid(), fd);
> +	if (FILE_LINES_SCANF(procfdinfo, "fanotify ino:%*x sdev:%*x mflags: %x mask:0 ignored_mask:%x",
> +				&mflags, &ignored_mask) || !ignored_mask) {
> +		tst_res(TFAIL, "The ignore mask did not survive");
> +	} else {
> +		tst_res(TPASS, "Found mark with ignore mask (ignored_mask=%x, mflags=%x) in %s",
> +				ignored_mask, mflags, procfdinfo);
> +	}
> +}
> +
>  static void event_res(int ttype, int group,
>  		      struct fanotify_event_metadata *event,
>  		      const char *filename)
> @@ -274,6 +325,12 @@ static void test_fanotify(unsigned int n)
>  		return;
>  	}
>  
> +	if (tc->ignore && tst_kvercmp(5, 19, 0) < 0) {
> +		tst_res(TCONF, "ignored mask on parent dir has undefined "
> +				"behavior on kernel < 5.19");
> +		return;
> +	}
> +
>  	create_fanotify_groups(tc);
>  
>  	/*
> @@ -326,6 +383,13 @@ static void test_fanotify(unsigned int n)
>  	 * got the FAN_CLOSE_NOWRITE event only on a non-directory.
>  	 */
>  	for (i = 1; i < NUM_GROUPS; i++) {
> +		/*
> +		 * Verify that ignore mask survived the modify event on child,
> +		 * which was not supposed to be sent to this group.
> +		 */
> +		if (tc->ignore)
> +			check_ignore_mask(fd_notify[i]);
> +
>  		ret = read(fd_notify[i], event_buf, EVENT_BUF_LEN);
>  		if (ret > 0) {
>  			event = (struct fanotify_event_metadata *)event_buf;
> -- 
> 2.25.1
>
Petr Vorel July 25, 2022, 11:23 a.m. UTC | #7
Hi Amir, Jan,

> OK, after Amir cleared my confusing things looks good to me. Feel free to
> add:

Thanks for your work on fanotify tests.
Patches are good as always, merged.

Kind regards,
Petr

> Reviewed-by: Jan Kara <jack@suse.cz>

> 								Honza
diff mbox series

Patch

diff --git a/testcases/kernel/syscalls/fanotify/fanotify09.c b/testcases/kernel/syscalls/fanotify/fanotify09.c
index 070ad9933..0eb83e2f8 100644
--- a/testcases/kernel/syscalls/fanotify/fanotify09.c
+++ b/testcases/kernel/syscalls/fanotify/fanotify09.c
@@ -27,6 +27,11 @@ 
  * Test case #5 is a regression test for commit:
  *
  *      7372e79c9eb9 fanotify: fix logic of reporting name info with watched parent
+ *
+ * Test cases #6-#7 are regression tests for commit:
+ * (from v5.19, unlikely to be backported thus not in .tags):
+ *
+ *      e730558adffb fanotify: consistent behavior for parent not watching children
  */
 
 #define _GNU_SOURCE
@@ -73,6 +78,7 @@  static struct tcase {
 	const char *tname;
 	struct fanotify_mark_type mark;
 	unsigned int ondir;
+	unsigned int ignore;
 	unsigned int report_name;
 	const char *close_nowrite;
 	int nevents;
@@ -83,6 +89,7 @@  static struct tcase {
 		INIT_FANOTIFY_MARK_TYPE(MOUNT),
 		0,
 		0,
+		0,
 		DIR_NAME,
 		1, 0,
 	},
@@ -91,6 +98,7 @@  static struct tcase {
 		INIT_FANOTIFY_MARK_TYPE(MOUNT),
 		FAN_ONDIR,
 		0,
+		0,
 		DIR_NAME,
 		2, 0,
 	},
@@ -99,6 +107,7 @@  static struct tcase {
 		INIT_FANOTIFY_MARK_TYPE(MOUNT),
 		FAN_ONDIR,
 		0,
+		0,
 		".",
 		2, 0
 	},
@@ -107,6 +116,7 @@  static struct tcase {
 		INIT_FANOTIFY_MARK_TYPE(INODE),
 		FAN_ONDIR,
 		0,
+		0,
 		DIR_NAME,
 		2, 0,
 	},
@@ -115,6 +125,7 @@  static struct tcase {
 		INIT_FANOTIFY_MARK_TYPE(MOUNT),
 		0,
 		0,
+		0,
 		FILE2_NAME,
 		2, FAN_CLOSE_NOWRITE,
 	},
@@ -122,10 +133,29 @@  static struct tcase {
 		"Events on non-dir child with both parent and mount marks and filename info",
 		INIT_FANOTIFY_MARK_TYPE(MOUNT),
 		0,
+		0,
 		FAN_REPORT_DFID_NAME,
 		FILE2_NAME,
 		2, FAN_CLOSE_NOWRITE,
 	},
+	{
+		"Events on non-dir child with ignore mask on parent",
+		INIT_FANOTIFY_MARK_TYPE(MOUNT),
+		0,
+		FAN_MARK_IGNORED_MASK,
+		0,
+		DIR_NAME,
+		1, 0,
+	},
+	{
+		"Events on non-dir children with surviving ignore mask on parent",
+		INIT_FANOTIFY_MARK_TYPE(MOUNT),
+		0,
+		FAN_MARK_IGNORED_MASK | FAN_MARK_IGNORED_SURV_MODIFY,
+		0,
+		FILE2_NAME,
+		2, FAN_CLOSE_NOWRITE,
+	},
 };
 
 static void create_fanotify_groups(struct tcase *tc)
@@ -140,13 +170,14 @@  static void create_fanotify_groups(struct tcase *tc)
 		 */
 		unsigned int report_name = tc->report_name;
 		unsigned int mask_flags = tc->ondir | FAN_EVENT_ON_CHILD;
-		unsigned int parent_mask;
+		unsigned int parent_mask, ignore = 0;
 
 		/*
 		 * The non-first groups do not request events on children and
-		 * subdirs.
+		 * subdirs and may set an ignore mask on parent dir.
 		 */
 		if (i > 0) {
+			ignore = tc->ignore;
 			report_name = 0;
 			mask_flags = 0;
 		}
@@ -168,10 +199,15 @@  static void create_fanotify_groups(struct tcase *tc)
 		 * but only the first group requests events on child.
 		 * The one mark with FAN_EVENT_ON_CHILD is needed for
 		 * setting the DCACHE_FSNOTIFY_PARENT_WATCHED dentry flag.
+		 *
+		 * The inode mark on non-first group is either with FAN_MODIFY
+		 * in mask or FAN_CLOSE_NOWRITE in ignore mask. In either case,
+		 * it is not expected to get the modify event on a child, nor
+		 * the close event on dir.
 		 */
 		parent_mask = FAN_MODIFY | tc->ondir | mask_flags;
-		SAFE_FANOTIFY_MARK(fd_notify[i], FAN_MARK_ADD,
-				    parent_mask,
+		SAFE_FANOTIFY_MARK(fd_notify[i], FAN_MARK_ADD | ignore,
+				    ignore ? FAN_CLOSE_NOWRITE : parent_mask,
 				    AT_FDCWD, ".");
 	}
 }
@@ -186,6 +222,21 @@  static void cleanup_fanotify_groups(void)
 	}
 }
 
+static void check_ignore_mask(int fd)
+{
+	unsigned int ignored_mask, mflags;
+	char procfdinfo[100];
+
+	sprintf(procfdinfo, "/proc/%d/fdinfo/%d", (int)getpid(), fd);
+	if (FILE_LINES_SCANF(procfdinfo, "fanotify ino:%*x sdev:%*x mflags: %x mask:0 ignored_mask:%x",
+				&mflags, &ignored_mask) || !ignored_mask) {
+		tst_res(TFAIL, "The ignore mask did not survive");
+	} else {
+		tst_res(TPASS, "Found mark with ignore mask (ignored_mask=%x, mflags=%x) in %s",
+				ignored_mask, mflags, procfdinfo);
+	}
+}
+
 static void event_res(int ttype, int group,
 		      struct fanotify_event_metadata *event,
 		      const char *filename)
@@ -274,6 +325,12 @@  static void test_fanotify(unsigned int n)
 		return;
 	}
 
+	if (tc->ignore && tst_kvercmp(5, 19, 0) < 0) {
+		tst_res(TCONF, "ignored mask on parent dir has undefined "
+				"behavior on kernel < 5.19");
+		return;
+	}
+
 	create_fanotify_groups(tc);
 
 	/*
@@ -326,6 +383,13 @@  static void test_fanotify(unsigned int n)
 	 * got the FAN_CLOSE_NOWRITE event only on a non-directory.
 	 */
 	for (i = 1; i < NUM_GROUPS; i++) {
+		/*
+		 * Verify that ignore mask survived the modify event on child,
+		 * which was not supposed to be sent to this group.
+		 */
+		if (tc->ignore)
+			check_ignore_mask(fd_notify[i]);
+
 		ret = read(fd_notify[i], event_buf, EVENT_BUF_LEN);
 		if (ret > 0) {
 			event = (struct fanotify_event_metadata *)event_buf;