aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2022-08-03 11:35:20 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2022-08-03 11:35:20 -0700
commita782e866497217f22c5d9014cbb7be8549151376 (patch)
treef1fd2e196c53618e2485d7bc04b654158fefa21f
parentMerge tag 'pull-work.namei' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs (diff)
parentfs: remove no_llseek (diff)
downloadwireguard-linux-a782e866497217f22c5d9014cbb7be8549151376.tar.xz
wireguard-linux-a782e866497217f22c5d9014cbb7be8549151376.zip
Merge tag 'pull-work.lseek' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull vfs lseek updates from Al Viro: "Jason's lseek series. Saner handling of 'lseek should fail with ESPIPE' - this gets rid of the magical no_llseek thing and makes checks consistent. In particular, the ad-hoc "can we do splice via internal pipe" checks got saner (and somewhat more permissive, which is what Jason had been after, AFAICT)" * tag 'pull-work.lseek' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: fs: remove no_llseek fs: check FMODE_LSEEK to control internal pipe splicing vfio: do not set FMODE_LSEEK flag dma-buf: remove useless FMODE_LSEEK flag fs: do not compare against ->llseek fs: clear or set FMODE_LSEEK based on llseek function
-rw-r--r--Documentation/filesystems/porting.rst8
-rw-r--r--drivers/dma-buf/dma-buf.c1
-rw-r--r--drivers/gpu/drm/drm_file.c3
-rw-r--r--drivers/vfio/vfio.c2
-rw-r--r--fs/coredump.c4
-rw-r--r--fs/file_table.c2
-rw-r--r--fs/open.c2
-rw-r--r--fs/overlayfs/copy_up.c3
-rw-r--r--fs/read_write.c17
-rw-r--r--fs/splice.c10
-rw-r--r--include/linux/fs.h2
-rw-r--r--kernel/bpf/bpf_iter.c3
12 files changed, 26 insertions, 31 deletions
diff --git a/Documentation/filesystems/porting.rst b/Documentation/filesystems/porting.rst
index 2e0e4f0e0c6f..aee9aaf9f3df 100644
--- a/Documentation/filesystems/porting.rst
+++ b/Documentation/filesystems/porting.rst
@@ -914,3 +914,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/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c
index 32f55640890c..3f08e0b960ec 100644
--- a/drivers/dma-buf/dma-buf.c
+++ b/drivers/dma-buf/dma-buf.c
@@ -549,7 +549,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);
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/drivers/vfio/vfio.c b/drivers/vfio/vfio.c
index e60b06f2ac22..521a3eabf0e1 100644
--- a/drivers/vfio/vfio.c
+++ b/drivers/vfio/vfio.c
@@ -1132,7 +1132,7 @@ static struct file *vfio_device_open(struct vfio_device *device)
* 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);
if (device->group->type == VFIO_NO_IOMMU)
dev_warn(device->dev, "vfio-noiommu device opened by user "
diff --git a/fs/coredump.c b/fs/coredump.c
index ebc43f960b64..9f4aae202109 100644
--- a/fs/coredump.c
+++ b/fs/coredump.c
@@ -816,9 +816,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/file_table.c b/fs/file_table.c
index 5424e3a8df5f..5727a63a7b67 100644
--- a/fs/file_table.c
+++ b/fs/file_table.c
@@ -235,6 +235,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)
+ 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 2790aac66e58..1177e8d1cf83 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -888,6 +888,8 @@ 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_mapping->a_ops && f->f_mapping->a_ops->direct_IO)
f->f_mode |= FMODE_CAN_ODIRECT;
diff --git a/fs/overlayfs/copy_up.c b/fs/overlayfs/copy_up.c
index 245e2cb62708..fdde6c56cc3d 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 0131d0df0476..ea59dd0095c2 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);
@@ -290,14 +284,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);
diff --git a/fs/splice.c b/fs/splice.c
index 047b79db8eb5..93a2c9bf6249 100644
--- a/fs/splice.c
+++ b/fs/splice.c
@@ -814,17 +814,15 @@ ssize_t splice_direct_to_actor(struct file *in, struct splice_desc *sd,
{
struct pipe_inode_info *pipe;
long ret, bytes;
- umode_t i_mode;
size_t len;
int i, flags, more;
/*
- * We require the input being a regular file, as we don't want to
- * randomly drop data for eg socket -> socket splicing. Use the
- * piped splicing for that!
+ * We require the input to be seekable, as we don't want to randomly
+ * drop data for eg socket -> socket splicing. Use the piped splicing
+ * for that!
*/
- i_mode = file_inode(in)->i_mode;
- if (unlikely(!S_ISREG(i_mode) && !S_ISBLK(i_mode)))
+ if (unlikely(!(in->f_mode & FMODE_LSEEK)))
return -EINVAL;
/*
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 7d32b7eabded..76f09f3ee4a5 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -3152,7 +3152,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 d5d96ceca105..8af0cbf9c0cd 100644
--- a/kernel/bpf/bpf_iter.c
+++ b/kernel/bpf/bpf_iter.c
@@ -81,10 +81,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,