The following patches has been applied to 6.0 but only patch#2 below has been applied to stable. This caused regression with nfs tests in all stable releases.
This patchset backports patches 1 and 3-6 to stable.
1. 868941b14441 fs: remove no_llseek 2. 97ef77c52b78 fs: check FMODE_LSEEK to control internal pipe splicing 3. 54ef7a47f67d vfio: do not set FMODE_LSEEK flag 4. c9eb2d427c1c dma-buf: remove useless FMODE_LSEEK flag 5. 4e3299eaddff fs: do not compare against ->llseek 6. e7478158e137 fs: clear or set FMODE_LSEEK based on llseek function
For 5.10.y and 5.4.y only, a revert of patch#2 is already included. Please apply patch#2, for 5.4.y and 5.10.y as well.
Thanks, Saeed
Jason A. Donenfeld (5): fs: clear or set FMODE_LSEEK based on llseek function fs: do not compare against ->llseek dma-buf: remove useless FMODE_LSEEK flag vfio: do not set FMODE_LSEEK flag fs: remove no_llseek
Documentation/filesystems/porting.rst | 8 ++++++++ drivers/dma-buf/dma-buf.c | 1 - drivers/gpu/drm/drm_file.c | 3 +-- drivers/vfio/vfio.c | 2 +- fs/coredump.c | 4 ++-- fs/file_table.c | 2 ++ fs/open.c | 4 ++++ fs/overlayfs/copy_up.c | 3 +-- fs/read_write.c | 17 +++-------------- include/linux/fs.h | 2 +- kernel/bpf/bpf_iter.c | 3 +-- 11 files changed, 24 insertions(+), 25 deletions(-)
From: "Jason A. Donenfeld" Jason@zx2c4.com
Pipe-like behaviour on llseek(2) (i.e. unconditionally failing with -ESPIPE) can be expresses in 3 ways: 1) ->llseek set to NULL in file_operations 2) ->llseek set to no_llseek in file_operations 3) FMODE_LSEEK *not* set in ->f_mode.
Enforce (3) in cases (1) and (2); that will allow to simplify the checks and eventually get rid of no_llseek boilerplate.
Signed-off-by: Jason A. Donenfeld Jason@zx2c4.com Signed-off-by: Al Viro viro@zeniv.linux.org.uk (cherry picked from commit e7478158e1378325907edfdd960eca98a1be405b) Conflicts: fs/open.c Cc: stable@vger.kernel.org Signed-off-by: Saeed Mirzamohammadi saeed.mirzamohammadi@oracle.com --- fs/file_table.c | 2 ++ fs/open.c | 4 ++++ 2 files changed, 6 insertions(+)
diff --git a/fs/file_table.c b/fs/file_table.c index e8c9016703ad..f675817be4ad 100644 --- a/fs/file_table.c +++ b/fs/file_table.c @@ -198,6 +198,8 @@ static struct file *alloc_file(const struct path *path, int flags, file->f_mapping = path->dentry->d_inode->i_mapping; file->f_wb_err = filemap_sample_wb_err(file->f_mapping); file->f_sb_err = file_sample_sb_err(file); + if (fop->llseek && fop->llseek != no_llseek) + file->f_mode |= FMODE_LSEEK; if ((file->f_mode & FMODE_READ) && likely(fop->read || fop->read_iter)) file->f_mode |= FMODE_CAN_READ; diff --git a/fs/open.c b/fs/open.c index 1ba1d2ab2ef0..38bf38d41418 100644 --- a/fs/open.c +++ b/fs/open.c @@ -834,6 +834,10 @@ static int do_dentry_open(struct file *f, if ((f->f_mode & FMODE_WRITE) && likely(f->f_op->write || f->f_op->write_iter)) f->f_mode |= FMODE_CAN_WRITE; + if ((f->f_mode & FMODE_LSEEK) && !f->f_op->llseek) + f->f_mode &= ~FMODE_LSEEK; + if ((f->f_mode & FMODE_LSEEK) && f->f_op->llseek == no_llseek) + f->f_mode &= ~FMODE_LSEEK;
f->f_write_hint = WRITE_LIFE_NOT_SET; f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);
From: "Jason A. Donenfeld" Jason@zx2c4.com
Now vfs_llseek() can simply check for FMODE_LSEEK; if it's set, we know that ->llseek() won't be NULL and if it's not we should just fail with -ESPIPE.
A couple of other places where we used to check for special values of ->llseek() (somewhat inconsistently) switched to checking FMODE_LSEEK.
Signed-off-by: Jason A. Donenfeld Jason@zx2c4.com Signed-off-by: Al Viro viro@zeniv.linux.org.uk (cherry picked from commit 4e3299eaddffd9d7d5b8bae28ad700bb775f02d0) Cc: stable@vger.kernel.org Signed-off-by: Saeed Mirzamohammadi saeed.mirzamohammadi@oracle.com --- fs/coredump.c | 4 ++-- fs/overlayfs/copy_up.c | 3 +-- fs/read_write.c | 11 +++-------- 3 files changed, 6 insertions(+), 12 deletions(-)
diff --git a/fs/coredump.c b/fs/coredump.c index 26eb5a095832..04ce02e30e23 100644 --- a/fs/coredump.c +++ b/fs/coredump.c @@ -886,9 +886,9 @@ static int __dump_skip(struct coredump_params *cprm, size_t nr) { static char zeroes[PAGE_SIZE]; struct file *file = cprm->file; - if (file->f_op->llseek && file->f_op->llseek != no_llseek) { + if (file->f_mode & FMODE_LSEEK) { if (dump_interrupted() || - file->f_op->llseek(file, nr, SEEK_CUR) < 0) + vfs_llseek(file, nr, SEEK_CUR) < 0) return 0; cprm->pos += nr; return 1; diff --git a/fs/overlayfs/copy_up.c b/fs/overlayfs/copy_up.c index e040970408d4..7636ec4d8b1c 100644 --- a/fs/overlayfs/copy_up.c +++ b/fs/overlayfs/copy_up.c @@ -226,8 +226,7 @@ static int ovl_copy_up_data(struct ovl_fs *ofs, struct path *old, /* Couldn't clone, so now we try to copy the data */
/* Check if lower fs supports seek operation */ - if (old_file->f_mode & FMODE_LSEEK && - old_file->f_op->llseek) + if (old_file->f_mode & FMODE_LSEEK) skip_hole = true;
while (len) { diff --git a/fs/read_write.c b/fs/read_write.c index 8d3ec975514d..b64527211b32 100644 --- a/fs/read_write.c +++ b/fs/read_write.c @@ -290,14 +290,9 @@ EXPORT_SYMBOL(default_llseek);
loff_t vfs_llseek(struct file *file, loff_t offset, int whence) { - loff_t (*fn)(struct file *, loff_t, int); - - fn = no_llseek; - if (file->f_mode & FMODE_LSEEK) { - if (file->f_op->llseek) - fn = file->f_op->llseek; - } - return fn(file, offset, whence); + if (!(file->f_mode & FMODE_LSEEK)) + return -ESPIPE; + return file->f_op->llseek(file, offset, whence); } EXPORT_SYMBOL(vfs_llseek);
From: "Jason A. Donenfeld" Jason@zx2c4.com
This is already set by anon_inode_getfile(), since dma_buf_fops has non-NULL ->llseek, so we don't need to set it here too.
Acked-by: Daniel Vetter daniel.vetter@ffwll.ch Acked-by: Sumit Semwal sumit.semwal@linaro.org Signed-off-by: Jason A. Donenfeld Jason@zx2c4.com Signed-off-by: Al Viro viro@zeniv.linux.org.uk (cherry picked from commit c9eb2d427c1c428e4f4e29f1e635b9a83236c015) Cc: stable@vger.kernel.org Signed-off-by: Saeed Mirzamohammadi saeed.mirzamohammadi@oracle.com --- drivers/dma-buf/dma-buf.c | 1 - 1 file changed, 1 deletion(-)
diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c index 968c3df2810e..3c3d0e2258b4 100644 --- a/drivers/dma-buf/dma-buf.c +++ b/drivers/dma-buf/dma-buf.c @@ -584,7 +584,6 @@ struct dma_buf *dma_buf_export(const struct dma_buf_export_info *exp_info) goto err_dmabuf; }
- file->f_mode |= FMODE_LSEEK; dmabuf->file = file;
mutex_init(&dmabuf->lock);
From: "Jason A. Donenfeld" Jason@zx2c4.com
This file does not support llseek, so don't set the flag advertising it.
Acked-by: Alex Williamson alex.williamson@redhat.com Signed-off-by: Jason A. Donenfeld Jason@zx2c4.com Signed-off-by: Al Viro viro@zeniv.linux.org.uk (cherry picked from commit 54ef7a47f67de9e87022a5310d1e8332af3e2696) Cc: stable@vger.kernel.org Signed-off-by: Saeed Mirzamohammadi saeed.mirzamohammadi@oracle.com --- drivers/vfio/vfio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/vfio/vfio.c b/drivers/vfio/vfio.c index 818e47fc0896..93346a76aa7b 100644 --- a/drivers/vfio/vfio.c +++ b/drivers/vfio/vfio.c @@ -1490,7 +1490,7 @@ static int vfio_group_get_device_fd(struct vfio_group *group, char *buf) * Appears to be missing by lack of need rather than * explicitly prevented. Now there's need. */ - filep->f_mode |= (FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE); + filep->f_mode |= (FMODE_PREAD | FMODE_PWRITE);
atomic_inc(&group->container_users);
From: "Jason A. Donenfeld" Jason@zx2c4.com
Now that all callers of ->llseek are going through vfs_llseek(), we don't gain anything by keeping no_llseek around. Nothing actually calls it and setting ->llseek to no_lseek is completely equivalent to leaving it NULL.
Longer term (== by the end of merge window) we want to remove all such intializations. To simplify the merge window this commit does *not* touch initializers - it only defines no_llseek as NULL (and simplifies the tests on file opening).
At -rc1 we'll need do a mechanical removal of no_llseek -
git grep -l -w no_llseek | grep -v porting.rst | while read i; do sed -i '/<no_llseek>/d' $i done would do it.
Signed-off-by: Jason A. Donenfeld Jason@zx2c4.com Signed-off-by: Al Viro viro@zeniv.linux.org.uk (cherry picked from commit 868941b14441282ba08761b770fc6cad69d5bdb7) Conflicts: fs/open.c Cc: stable@vger.kernel.org Signed-off-by: Saeed Mirzamohammadi saeed.mirzamohammadi@oracle.com --- Documentation/filesystems/porting.rst | 8 ++++++++ drivers/gpu/drm/drm_file.c | 3 +-- fs/file_table.c | 2 +- fs/read_write.c | 6 ------ include/linux/fs.h | 2 +- kernel/bpf/bpf_iter.c | 3 +-- 6 files changed, 12 insertions(+), 12 deletions(-)
diff --git a/Documentation/filesystems/porting.rst b/Documentation/filesystems/porting.rst index bf19fd6b86e7..9d362f80a644 100644 --- a/Documentation/filesystems/porting.rst +++ b/Documentation/filesystems/porting.rst @@ -908,3 +908,11 @@ Calling conventions for file_open_root() changed; now it takes struct path * instead of passing mount and dentry separately. For callers that used to pass <mnt, mnt->mnt_root> pair (i.e. the root of given mount), a new helper is provided - file_open_root_mnt(). In-tree users adjusted. + +--- + +**mandatory** + +no_llseek is gone; don't set .llseek to that - just leave it NULL instead. +Checks for "does that file have llseek(2), or should it fail with ESPIPE" +should be done by looking at FMODE_LSEEK in file->f_mode. diff --git a/drivers/gpu/drm/drm_file.c b/drivers/gpu/drm/drm_file.c index ed25168619fc..dc7d2e5b16c8 100644 --- a/drivers/gpu/drm/drm_file.c +++ b/drivers/gpu/drm/drm_file.c @@ -552,8 +552,7 @@ EXPORT_SYMBOL(drm_release_noglobal); * Since events are used by the KMS API for vblank and page flip completion this * means all modern display drivers must use it. * - * @offset is ignored, DRM events are read like a pipe. Therefore drivers also - * must set the &file_operation.llseek to no_llseek(). Polling support is + * @offset is ignored, DRM events are read like a pipe. Polling support is * provided by drm_poll(). * * This function will only ever read a full event. Therefore userspace must diff --git a/fs/file_table.c b/fs/file_table.c index f675817be4ad..652b70841df6 100644 --- a/fs/file_table.c +++ b/fs/file_table.c @@ -198,7 +198,7 @@ static struct file *alloc_file(const struct path *path, int flags, file->f_mapping = path->dentry->d_inode->i_mapping; file->f_wb_err = filemap_sample_wb_err(file->f_mapping); file->f_sb_err = file_sample_sb_err(file); - if (fop->llseek && fop->llseek != no_llseek) + if (fop->llseek) file->f_mode |= FMODE_LSEEK; if ((file->f_mode & FMODE_READ) && likely(fop->read || fop->read_iter)) diff --git a/fs/read_write.c b/fs/read_write.c index b64527211b32..582beb67e48e 100644 --- a/fs/read_write.c +++ b/fs/read_write.c @@ -227,12 +227,6 @@ loff_t noop_llseek(struct file *file, loff_t offset, int whence) } EXPORT_SYMBOL(noop_llseek);
-loff_t no_llseek(struct file *file, loff_t offset, int whence) -{ - return -ESPIPE; -} -EXPORT_SYMBOL(no_llseek); - loff_t default_llseek(struct file *file, loff_t offset, int whence) { struct inode *inode = file_inode(file); diff --git a/include/linux/fs.h b/include/linux/fs.h index 76162f046670..f5eac9d76e9d 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -3174,7 +3174,7 @@ extern long do_splice_direct(struct file *in, loff_t *ppos, struct file *out, extern void file_ra_state_init(struct file_ra_state *ra, struct address_space *mapping); extern loff_t noop_llseek(struct file *file, loff_t offset, int whence); -extern loff_t no_llseek(struct file *file, loff_t offset, int whence); +#define no_llseek NULL extern loff_t vfs_setpos(struct file *file, loff_t offset, loff_t maxsize); extern loff_t generic_file_llseek(struct file *file, loff_t offset, int whence); extern loff_t generic_file_llseek_size(struct file *file, loff_t offset, diff --git a/kernel/bpf/bpf_iter.c b/kernel/bpf/bpf_iter.c index b2ee45064e06..60e8f611954e 100644 --- a/kernel/bpf/bpf_iter.c +++ b/kernel/bpf/bpf_iter.c @@ -80,10 +80,9 @@ static bool bpf_iter_support_resched(struct seq_file *seq) #define MAX_ITER_OBJECTS 1000000
/* bpf_seq_read, a customized and simpler version for bpf iterator. - * no_llseek is assumed for this file. * The following are differences from seq_read(): * . fixed buffer size (PAGE_SIZE) - * . assuming no_llseek + * . assuming NULL ->llseek() * . stop() may call bpf program, handling potential overflow there */ static ssize_t bpf_seq_read(struct file *file, char __user *buf, size_t size,
On Mon, Oct 17, 2022 at 12:20:01PM -0700, Saeed Mirzamohammadi wrote:
The following patches has been applied to 6.0 but only patch#2 below has been applied to stable. This caused regression with nfs tests in all stable releases.
This patchset backports patches 1 and 3-6 to stable.
- 868941b14441 fs: remove no_llseek
- 97ef77c52b78 fs: check FMODE_LSEEK to control internal pipe splicing
- 54ef7a47f67d vfio: do not set FMODE_LSEEK flag
- c9eb2d427c1c dma-buf: remove useless FMODE_LSEEK flag
- 4e3299eaddff fs: do not compare against ->llseek
- e7478158e137 fs: clear or set FMODE_LSEEK based on llseek function
For 5.10.y and 5.4.y only, a revert of patch#2 is already included. Please apply patch#2, for 5.4.y and 5.10.y as well.
I am sorry, I really do not understand here.
You list these commits in a specific order, yet the patches you send are in a different order.
And they don't apply to 5.10 or older.
Can you resend proper patch series, for each stable branch that you want these applied to, so that I can correctly queue them up?
thanks,
greg k-h
On Mon, Oct 17, 2022 at 9:20 PM Saeed Mirzamohammadi saeed.mirzamohammadi@oracle.com wrote:
The following patches has been applied to 6.0 but only patch#2 below has been applied to stable. This caused regression with nfs tests in all stable releases.
This patchset backports patches 1 and 3-6 to stable.
- 868941b14441 fs: remove no_llseek
- 97ef77c52b78 fs: check FMODE_LSEEK to control internal pipe splicing
- 54ef7a47f67d vfio: do not set FMODE_LSEEK flag
- c9eb2d427c1c dma-buf: remove useless FMODE_LSEEK flag
- 4e3299eaddff fs: do not compare against ->llseek
- e7478158e137 fs: clear or set FMODE_LSEEK based on llseek function
For 5.10.y and 5.4.y only, a revert of patch#2 is already included. Please apply patch#2, for 5.4.y and 5.10.y as well.
This is confusing and there's no way Greg is going to do this right given the limited information you've provided and wrong ordering of the patches. I couldn't really even follow this without some detective work, and I wrote these patches.
Here are your options: - Let the revert of "97ef77c52b78 fs: check FMODE_LSEEK to control internal pipe splicing" work its way into all stable trees; or - Send a proper backport series for each and every stable kernel, depending on what each one needs. Send these as different patchsets, marked with the version number it applies to. Make sure they apply, compile, and work correctly.
Anything short of those is going to lead to chaos.
Jason
linux-stable-mirror@lists.linaro.org