Skip to contentSkip to conversation

backing-file: inherit FMODE_NONOTIFY from the user file

PATCH Edvard Conrad 2 participants 2 messages Oct 27 – Oct 28

Subsystems (2)
lore
Share & tools
lore
#0 lore raw
Quoted 1 line · Amir Goldstein

Any chance you can post this as an LTP test?

Yes. Written and verified, I will post it to the LTP list shortly as syscalls/fanotify26. Two cases: a mark on the overlay only, which passes on every kernel and keeps the test from passing for the wrong reason, and a mark on the overlay plus the backing filesystem, which is the shape that deadlocks.

Quoted 3 lines

Urgh I hate how special case this is.

How about something like below (untested)

Agreed on the shape, and it covers backing_tmpfile_open() as well, which mine did not. As posted it does not fix the deadlock though:

Review

Quoted 2 lines
(quoted diff) +1 -1
-       f->f_mode       = OPEN_FMODE(flags);
+       f->f_mode       = OPEN_FMODE(flags) | fmode;

Five lines further down init_file() calls

	file_set_fsnotify_mode(f, FMODE_NONOTIFY_PERM);

and that helper clears FMODE_FSNOTIFY_MASK before it sets its argument, so the inherited FMODE_NONOTIFY is dropped again. The backing file ends up at FMODE_NONOTIFY_PERM, which is not FMODE_FSNOTIFY_NONE(), so fsnotify_open_perm_and_set_mode() does not take its early return and still raises FS_OPEN_PERM on the real path.

Measured in a VM on a defconfig + OVERLAY_FS + FANOTIFY + FANOTIFY_ACCESS_PERMISSIONS build of this tree, with the reproducer from the patch and with the LTP test:

  kernel                        reproducer    fanotify26
  mainline                      hangs         1 pass 1 fail
  v1 (fs/backing-file.c)        ok            2 pass
  your diff as posted           hangs         1 pass 1 fail
  v2                            ok            2 pass

v2 keeps your structure and routes the fsnotify part through file_set_fsnotify_mode() instead:

	fmode_t fsnotify_mode = fmode & FMODE_FSNOTIFY_MASK;
	...
	f->f_mode	= OPEN_FMODE(flags) | fmode;
	file_set_fsnotify_mode(f, fsnotify_mode ? fsnotify_mode :
						  FMODE_NONOTIFY_PERM);

One deliberate difference from your version: it inherits only the "no events at all" mode rather than masking FMODE_NONOTIFY out of whatever the user file carries. A user file in the HSM mode (FMODE_NONOTIFY | FMODE_NONOTIFY_PERM) would otherwise leave its backing file fully silent, suppressing the events on real files that bc2473c90fca deliberately enabled.

v2 follows in this thread.

Thanks,
Edvard

Reviewed-by
#1 lore raw
Quoted 10 lines · Edvard Conrad
Quoted 1 line · Amir Goldstein

Any chance you can post this as an LTP test?

Yes. Written and verified, I will post it to the LTP list shortly as syscalls/fanotify26. Two cases: a mark on the overlay only, which passes on every kernel and keeps the test from passing for the wrong reason, and a mark on the overlay plus the backing filesystem, which is the shape that deadlocks.

Great!

Quoted 6 lines
Quoted 3 lines

Urgh I hate how special case this is.

How about something like below (untested)

Agreed on the shape, and it covers backing_tmpfile_open() as well, which mine did not.

There is no code that adds NONOTIFY to backing_tmpfile_open() the only code that could add NONOTIFY to backing file is from dentry_open_nonotify()

Quoted 34 lines

As posted it does not fix the deadlock though:

Review

Quoted 2 lines
(quoted diff) +1 -1
-       f->f_mode       = OPEN_FMODE(flags);
+       f->f_mode       = OPEN_FMODE(flags) | fmode;

Five lines further down init_file() calls

        file_set_fsnotify_mode(f, FMODE_NONOTIFY_PERM);

and that helper clears FMODE_FSNOTIFY_MASK before it sets its argument, so the inherited FMODE_NONOTIFY is dropped again. The backing file ends up at FMODE_NONOTIFY_PERM, which is not FMODE_FSNOTIFY_NONE(), so fsnotify_open_perm_and_set_mode() does not take its early return and still raises FS_OPEN_PERM on the real path.

Measured in a VM on a defconfig + OVERLAY_FS + FANOTIFY + FANOTIFY_ACCESS_PERMISSIONS build of this tree, with the reproducer from the patch and with the LTP test:

  kernel                        reproducer    fanotify26
  mainline                      hangs         1 pass 1 fail
  v1 (fs/backing-file.c)        ok            2 pass
  your diff as posted           hangs         1 pass 1 fail
  v2                            ok            2 pass

v2 keeps your structure and routes the fsnotify part through file_set_fsnotify_mode() instead:

        fmode_t fsnotify_mode = fmode & FMODE_FSNOTIFY_MASK;
        ...
        f->f_mode       = OPEN_FMODE(flags) | fmode;
        file_set_fsnotify_mode(f, fsnotify_mode ? fsnotify_mode :
                                                  FMODE_NONOTIFY_PERM);
Quoted 6 lines

One deliberate difference from your version: it inherits only the "no events at all" mode rather than masking FMODE_NONOTIFY out of whatever the user file carries. A user file in the HSM mode (FMODE_NONOTIFY | FMODE_NONOTIFY_PERM) would otherwise leave its backing file fully silent, suppressing the events on real files that bc2473c90fca deliberately enabled.

The problem is that I wanted something more generic and v2 is still very much special casing NONOTIFY and much bigger than v1, so there is no gain.

Let's admit that I gave you a bad advise and a wrong sketch patch and feel free to add to v1:

BTW, pls remove Assisted-by it is not needed and remove the newline after cc: stable

Thanks,
Amir.