On Tue, Jun 27, 2023 at 7:55 PM Ahelenia Ziemiańska <nabijaczleweli@xxxxxxxxxxxxxxxxxx> wrote: > > The current behaviour caused an asymmetry where some write APIs > (write, sendfile) would notify the written-to/read-from objects, > but splice wouldn't. > > This affected userspace which uses inotify, most notably coreutils > tail -f, to monitor pipes. > If the pipe buffer had been filled by a splice-family function: > * tail wouldn't know and thus wouldn't service the pipe, and > * all writes to the pipe would block because it's full, > thus service was denied. > (For the particular case of tail -f this could be worked around > with ---disable-inotify.) > > Fixes: 983652c69199 ("splice: report related fsnotify events") > Link: https://lore.kernel.org/linux-fsdevel/jbyihkyk5dtaohdwjyivambb2gffyjs3dodpofafnkkunxq7bu@jngkdxx65pux/t/#u > Link: https://bugs.debian.org/1039488 > Signed-off-by: Ahelenia Ziemiańska <nabijaczleweli@xxxxxxxxxxxxxxxxxx> > Reviewed-by: Amir Goldstein <amir73il@xxxxxxxxx> > --- > fs/splice.c | 31 ++++++++++++++----------------- > 1 file changed, 14 insertions(+), 17 deletions(-) > > diff --git a/fs/splice.c b/fs/splice.c > index 3e06611d19ae..e16f4f032d2f 100644 > --- a/fs/splice.c > +++ b/fs/splice.c > @@ -1154,10 +1154,8 @@ long do_splice(struct file *in, loff_t *off_in, struct file *out, > if ((in->f_flags | out->f_flags) & O_NONBLOCK) > flags |= SPLICE_F_NONBLOCK; > > - return splice_pipe_to_pipe(ipipe, opipe, len, flags); > - } > - > - if (ipipe) { > + ret = splice_pipe_to_pipe(ipipe, opipe, len, flags); > + } else if (ipipe) { > if (off_in) > return -ESPIPE; > if (off_out) { > @@ -1182,18 +1180,15 @@ long do_splice(struct file *in, loff_t *off_in, struct file *out, > ret = do_splice_from(ipipe, out, &offset, len, flags); > file_end_write(out); > > - if (ret > 0) > - fsnotify_modify(out); > - > if (!off_out) > out->f_pos = offset; > else > *off_out = offset; > > - return ret; > - } > - > - if (opipe) { > + // splice_write-> already marked out > + // as modified via vfs_iter_write() > + goto noaccessout; > + } else if (opipe) { > if (off_out) > return -ESPIPE; > if (off_in) { > @@ -1209,18 +1204,20 @@ long do_splice(struct file *in, loff_t *off_in, struct file *out, > > ret = splice_file_to_pipe(in, opipe, &offset, len, flags); > > - if (ret > 0) > - fsnotify_access(in); > - > if (!off_in) > in->f_pos = offset; > else > *off_in = offset; > + } else > + return -EINVAL; > > - return ret; > - } > + if (ret > 0) > + fsnotify_modify(out); > +noaccessout: > + if (ret > 0) > + fsnotify_access(in); > As I wrote, I don't like this special case. I prefer that we generate double IN_MODIFY than having to maintain unreadable code. Let's see what Jan has to say about this. Thanks, Amir.