Commit a782e866 authored by Linus Torvalds's avatar Linus Torvalds

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
parents d9395512 868941b1
...@@ -914,3 +914,11 @@ Calling conventions for file_open_root() changed; now it takes struct path * ...@@ -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 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 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. 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.
...@@ -549,7 +549,6 @@ struct dma_buf *dma_buf_export(const struct dma_buf_export_info *exp_info) ...@@ -549,7 +549,6 @@ struct dma_buf *dma_buf_export(const struct dma_buf_export_info *exp_info)
goto err_dmabuf; goto err_dmabuf;
} }
file->f_mode |= FMODE_LSEEK;
dmabuf->file = file; dmabuf->file = file;
mutex_init(&dmabuf->lock); mutex_init(&dmabuf->lock);
......
...@@ -552,8 +552,7 @@ EXPORT_SYMBOL(drm_release_noglobal); ...@@ -552,8 +552,7 @@ EXPORT_SYMBOL(drm_release_noglobal);
* Since events are used by the KMS API for vblank and page flip completion this * Since events are used by the KMS API for vblank and page flip completion this
* means all modern display drivers must use it. * means all modern display drivers must use it.
* *
* @offset is ignored, DRM events are read like a pipe. Therefore drivers also * @offset is ignored, DRM events are read like a pipe. Polling support is
* must set the &file_operation.llseek to no_llseek(). Polling support is
* provided by drm_poll(). * provided by drm_poll().
* *
* This function will only ever read a full event. Therefore userspace must * This function will only ever read a full event. Therefore userspace must
......
...@@ -1132,7 +1132,7 @@ static struct file *vfio_device_open(struct vfio_device *device) ...@@ -1132,7 +1132,7 @@ static struct file *vfio_device_open(struct vfio_device *device)
* Appears to be missing by lack of need rather than * Appears to be missing by lack of need rather than
* explicitly prevented. Now there's need. * 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) if (device->group->type == VFIO_NO_IOMMU)
dev_warn(device->dev, "vfio-noiommu device opened by user " dev_warn(device->dev, "vfio-noiommu device opened by user "
......
...@@ -816,9 +816,9 @@ static int __dump_skip(struct coredump_params *cprm, size_t nr) ...@@ -816,9 +816,9 @@ static int __dump_skip(struct coredump_params *cprm, size_t nr)
{ {
static char zeroes[PAGE_SIZE]; static char zeroes[PAGE_SIZE];
struct file *file = cprm->file; 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() || if (dump_interrupted() ||
file->f_op->llseek(file, nr, SEEK_CUR) < 0) vfs_llseek(file, nr, SEEK_CUR) < 0)
return 0; return 0;
cprm->pos += nr; cprm->pos += nr;
return 1; return 1;
......
...@@ -235,6 +235,8 @@ static struct file *alloc_file(const struct path *path, int flags, ...@@ -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_mapping = path->dentry->d_inode->i_mapping;
file->f_wb_err = filemap_sample_wb_err(file->f_mapping); file->f_wb_err = filemap_sample_wb_err(file->f_mapping);
file->f_sb_err = file_sample_sb_err(file); file->f_sb_err = file_sample_sb_err(file);
if (fop->llseek)
file->f_mode |= FMODE_LSEEK;
if ((file->f_mode & FMODE_READ) && if ((file->f_mode & FMODE_READ) &&
likely(fop->read || fop->read_iter)) likely(fop->read || fop->read_iter))
file->f_mode |= FMODE_CAN_READ; file->f_mode |= FMODE_CAN_READ;
......
...@@ -888,6 +888,8 @@ static int do_dentry_open(struct file *f, ...@@ -888,6 +888,8 @@ static int do_dentry_open(struct file *f,
if ((f->f_mode & FMODE_WRITE) && if ((f->f_mode & FMODE_WRITE) &&
likely(f->f_op->write || f->f_op->write_iter)) likely(f->f_op->write || f->f_op->write_iter))
f->f_mode |= FMODE_CAN_WRITE; 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) if (f->f_mapping->a_ops && f->f_mapping->a_ops->direct_IO)
f->f_mode |= FMODE_CAN_ODIRECT; f->f_mode |= FMODE_CAN_ODIRECT;
......
...@@ -226,8 +226,7 @@ static int ovl_copy_up_data(struct ovl_fs *ofs, struct path *old, ...@@ -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 */ /* Couldn't clone, so now we try to copy the data */
/* Check if lower fs supports seek operation */ /* Check if lower fs supports seek operation */
if (old_file->f_mode & FMODE_LSEEK && if (old_file->f_mode & FMODE_LSEEK)
old_file->f_op->llseek)
skip_hole = true; skip_hole = true;
while (len) { while (len) {
......
...@@ -227,12 +227,6 @@ loff_t noop_llseek(struct file *file, loff_t offset, int whence) ...@@ -227,12 +227,6 @@ loff_t noop_llseek(struct file *file, loff_t offset, int whence)
} }
EXPORT_SYMBOL(noop_llseek); 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) loff_t default_llseek(struct file *file, loff_t offset, int whence)
{ {
struct inode *inode = file_inode(file); struct inode *inode = file_inode(file);
...@@ -290,14 +284,9 @@ EXPORT_SYMBOL(default_llseek); ...@@ -290,14 +284,9 @@ EXPORT_SYMBOL(default_llseek);
loff_t vfs_llseek(struct file *file, loff_t offset, int whence) loff_t vfs_llseek(struct file *file, loff_t offset, int whence)
{ {
loff_t (*fn)(struct file *, loff_t, int); if (!(file->f_mode & FMODE_LSEEK))
return -ESPIPE;
fn = no_llseek; return file->f_op->llseek(file, offset, whence);
if (file->f_mode & FMODE_LSEEK) {
if (file->f_op->llseek)
fn = file->f_op->llseek;
}
return fn(file, offset, whence);
} }
EXPORT_SYMBOL(vfs_llseek); EXPORT_SYMBOL(vfs_llseek);
......
...@@ -814,17 +814,15 @@ ssize_t splice_direct_to_actor(struct file *in, struct splice_desc *sd, ...@@ -814,17 +814,15 @@ ssize_t splice_direct_to_actor(struct file *in, struct splice_desc *sd,
{ {
struct pipe_inode_info *pipe; struct pipe_inode_info *pipe;
long ret, bytes; long ret, bytes;
umode_t i_mode;
size_t len; size_t len;
int i, flags, more; int i, flags, more;
/* /*
* We require the input being a regular file, as we don't want to * We require the input to be seekable, as we don't want to randomly
* randomly drop data for eg socket -> socket splicing. Use the * drop data for eg socket -> socket splicing. Use the piped splicing
* piped splicing for that! * for that!
*/ */
i_mode = file_inode(in)->i_mode; if (unlikely(!(in->f_mode & FMODE_LSEEK)))
if (unlikely(!S_ISREG(i_mode) && !S_ISBLK(i_mode)))
return -EINVAL; return -EINVAL;
/* /*
......
...@@ -3152,7 +3152,7 @@ extern long do_splice_direct(struct file *in, loff_t *ppos, struct file *out, ...@@ -3152,7 +3152,7 @@ extern long do_splice_direct(struct file *in, loff_t *ppos, struct file *out,
extern void extern void
file_ra_state_init(struct file_ra_state *ra, struct address_space *mapping); 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 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 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(struct file *file, loff_t offset, int whence);
extern loff_t generic_file_llseek_size(struct file *file, loff_t offset, extern loff_t generic_file_llseek_size(struct file *file, loff_t offset,
......
...@@ -81,10 +81,9 @@ static bool bpf_iter_support_resched(struct seq_file *seq) ...@@ -81,10 +81,9 @@ static bool bpf_iter_support_resched(struct seq_file *seq)
#define MAX_ITER_OBJECTS 1000000 #define MAX_ITER_OBJECTS 1000000
/* bpf_seq_read, a customized and simpler version for bpf iterator. /* 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(): * The following are differences from seq_read():
* . fixed buffer size (PAGE_SIZE) * . fixed buffer size (PAGE_SIZE)
* . assuming no_llseek * . assuming NULL ->llseek()
* . stop() may call bpf program, handling potential overflow there * . stop() may call bpf program, handling potential overflow there
*/ */
static ssize_t bpf_seq_read(struct file *file, char __user *buf, size_t size, static ssize_t bpf_seq_read(struct file *file, char __user *buf, size_t size,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment