fs: move FMODE_UNSIGNED_OFFSET to fop_flags

This is another flag that is statically set and doesn't need to use up
an FMODE_* bit. Move it to ->fop_flags and free up another FMODE_* bit.

(1) mem_open() used from proc_mem_operations
(2) adi_open() used from adi_fops
(3) drm_open_helper():
    (3.1) accel_open() used from DRM_ACCEL_FOPS
    (3.2) drm_open() used from
    (3.2.1) amdgpu_driver_kms_fops
    (3.2.2) psb_gem_fops
    (3.2.3) i915_driver_fops
    (3.2.4) nouveau_driver_fops
    (3.2.5) panthor_drm_driver_fops
    (3.2.6) radeon_driver_kms_fops
    (3.2.7) tegra_drm_fops
    (3.2.8) vmwgfx_driver_fops
    (3.2.9) xe_driver_fops
    (3.2.10) DRM_GEM_FOPS
    (3.2.11) DEFINE_DRM_GEM_DMA_FOPS
(4) struct memdev sets fmode flags based on type of device opened. For
    devices using struct mem_fops unsigned offset is used.

Mark all these file operations as FOP_UNSIGNED_OFFSET and add asserts
into the open helper to ensure that the flag is always set.

Link: https://lore.kernel.org/r/20240809-work-fop_unsigned-v1-1-658e054d893e@kernel.org
Reviewed-by: Jeff Layton <jlayton@kernel.org>
Reviewed-by: Jan Kara <jack@suse.cz>
Signed-off-by: Christian Brauner <brauner@kernel.org>
This commit is contained in:
Christian Brauner 2024-08-09 12:38:56 +02:00
parent 8447d848e1
commit 641bb4394f
18 changed files with 27 additions and 21 deletions

View File

@ -14,12 +14,6 @@
#define MAX_BUF_SZ PAGE_SIZE #define MAX_BUF_SZ PAGE_SIZE
static int adi_open(struct inode *inode, struct file *file)
{
file->f_mode |= FMODE_UNSIGNED_OFFSET;
return 0;
}
static int read_mcd_tag(unsigned long addr) static int read_mcd_tag(unsigned long addr)
{ {
long err; long err;
@ -206,9 +200,9 @@ static loff_t adi_llseek(struct file *file, loff_t offset, int whence)
static const struct file_operations adi_fops = { static const struct file_operations adi_fops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.llseek = adi_llseek, .llseek = adi_llseek,
.open = adi_open,
.read = adi_read, .read = adi_read,
.write = adi_write, .write = adi_write,
.fop_flags = FOP_UNSIGNED_OFFSET,
}; };
static struct miscdevice adi_miscdev = { static struct miscdevice adi_miscdev = {

View File

@ -643,6 +643,7 @@ static const struct file_operations __maybe_unused mem_fops = {
.get_unmapped_area = get_unmapped_area_mem, .get_unmapped_area = get_unmapped_area_mem,
.mmap_capabilities = memory_mmap_capabilities, .mmap_capabilities = memory_mmap_capabilities,
#endif #endif
.fop_flags = FOP_UNSIGNED_OFFSET,
}; };
static const struct file_operations null_fops = { static const struct file_operations null_fops = {
@ -693,7 +694,7 @@ static const struct memdev {
umode_t mode; umode_t mode;
} devlist[] = { } devlist[] = {
#ifdef CONFIG_DEVMEM #ifdef CONFIG_DEVMEM
[DEVMEM_MINOR] = { "mem", &mem_fops, FMODE_UNSIGNED_OFFSET, 0 }, [DEVMEM_MINOR] = { "mem", &mem_fops, 0, 0 },
#endif #endif
[3] = { "null", &null_fops, FMODE_NOWAIT, 0666 }, [3] = { "null", &null_fops, FMODE_NOWAIT, 0666 },
#ifdef CONFIG_DEVPORT #ifdef CONFIG_DEVPORT

View File

@ -2908,6 +2908,7 @@ static const struct file_operations amdgpu_driver_kms_fops = {
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
.show_fdinfo = drm_show_fdinfo, .show_fdinfo = drm_show_fdinfo,
#endif #endif
.fop_flags = FOP_UNSIGNED_OFFSET,
}; };
int amdgpu_file_to_fpriv(struct file *filp, struct amdgpu_fpriv **fpriv) int amdgpu_file_to_fpriv(struct file *filp, struct amdgpu_fpriv **fpriv)

View File

@ -318,6 +318,8 @@ int drm_open_helper(struct file *filp, struct drm_minor *minor)
if (dev->switch_power_state != DRM_SWITCH_POWER_ON && if (dev->switch_power_state != DRM_SWITCH_POWER_ON &&
dev->switch_power_state != DRM_SWITCH_POWER_DYNAMIC_OFF) dev->switch_power_state != DRM_SWITCH_POWER_DYNAMIC_OFF)
return -EINVAL; return -EINVAL;
if (WARN_ON_ONCE(!(filp->f_op->fop_flags & FOP_UNSIGNED_OFFSET)))
return -EINVAL;
drm_dbg_core(dev, "comm=\"%s\", pid=%d, minor=%d\n", drm_dbg_core(dev, "comm=\"%s\", pid=%d, minor=%d\n",
current->comm, task_pid_nr(current), minor->index); current->comm, task_pid_nr(current), minor->index);
@ -335,7 +337,6 @@ int drm_open_helper(struct file *filp, struct drm_minor *minor)
} }
filp->private_data = priv; filp->private_data = priv;
filp->f_mode |= FMODE_UNSIGNED_OFFSET;
priv->filp = filp; priv->filp = filp;
mutex_lock(&dev->filelist_mutex); mutex_lock(&dev->filelist_mutex);

View File

@ -498,6 +498,7 @@ static const struct file_operations psb_gem_fops = {
.mmap = drm_gem_mmap, .mmap = drm_gem_mmap,
.poll = drm_poll, .poll = drm_poll,
.read = drm_read, .read = drm_read,
.fop_flags = FOP_UNSIGNED_OFFSET,
}; };
static const struct drm_driver driver = { static const struct drm_driver driver = {

View File

@ -1671,6 +1671,7 @@ static const struct file_operations i915_driver_fops = {
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
.show_fdinfo = drm_show_fdinfo, .show_fdinfo = drm_show_fdinfo,
#endif #endif
.fop_flags = FOP_UNSIGNED_OFFSET,
}; };
static int static int

View File

@ -1274,6 +1274,7 @@ nouveau_driver_fops = {
.compat_ioctl = nouveau_compat_ioctl, .compat_ioctl = nouveau_compat_ioctl,
#endif #endif
.llseek = noop_llseek, .llseek = noop_llseek,
.fop_flags = FOP_UNSIGNED_OFFSET,
}; };
static struct drm_driver static struct drm_driver

View File

@ -520,6 +520,7 @@ static const struct file_operations radeon_driver_kms_fops = {
#ifdef CONFIG_COMPAT #ifdef CONFIG_COMPAT
.compat_ioctl = radeon_kms_compat_ioctl, .compat_ioctl = radeon_kms_compat_ioctl,
#endif #endif
.fop_flags = FOP_UNSIGNED_OFFSET,
}; };
static const struct drm_ioctl_desc radeon_ioctls_kms[] = { static const struct drm_ioctl_desc radeon_ioctls_kms[] = {

View File

@ -801,6 +801,7 @@ static const struct file_operations tegra_drm_fops = {
.read = drm_read, .read = drm_read,
.compat_ioctl = drm_compat_ioctl, .compat_ioctl = drm_compat_ioctl,
.llseek = noop_llseek, .llseek = noop_llseek,
.fop_flags = FOP_UNSIGNED_OFFSET,
}; };
static int tegra_drm_context_cleanup(int id, void *p, void *data) static int tegra_drm_context_cleanup(int id, void *p, void *data)

View File

@ -1609,6 +1609,7 @@ static const struct file_operations vmwgfx_driver_fops = {
.compat_ioctl = vmw_compat_ioctl, .compat_ioctl = vmw_compat_ioctl,
#endif #endif
.llseek = noop_llseek, .llseek = noop_llseek,
.fop_flags = FOP_UNSIGNED_OFFSET,
}; };
static const struct drm_driver driver = { static const struct drm_driver driver = {

View File

@ -238,6 +238,7 @@ static const struct file_operations xe_driver_fops = {
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
.show_fdinfo = drm_show_fdinfo, .show_fdinfo = drm_show_fdinfo,
#endif #endif
.fop_flags = FOP_UNSIGNED_OFFSET,
}; };
static struct drm_driver driver = { static struct drm_driver driver = {

View File

@ -827,12 +827,9 @@ static int __mem_open(struct inode *inode, struct file *file, unsigned int mode)
static int mem_open(struct inode *inode, struct file *file) static int mem_open(struct inode *inode, struct file *file)
{ {
int ret = __mem_open(inode, file, PTRACE_MODE_ATTACH); if (WARN_ON_ONCE(!(file->f_op->fop_flags & FOP_UNSIGNED_OFFSET)))
return -EINVAL;
/* OK to pass negative loff_t, we can catch out-of-range */ return __mem_open(inode, file, PTRACE_MODE_ATTACH);
file->f_mode |= FMODE_UNSIGNED_OFFSET;
return ret;
} }
static ssize_t mem_rw(struct file *file, char __user *buf, static ssize_t mem_rw(struct file *file, char __user *buf,
@ -932,6 +929,7 @@ static const struct file_operations proc_mem_operations = {
.write = mem_write, .write = mem_write,
.open = mem_open, .open = mem_open,
.release = mem_release, .release = mem_release,
.fop_flags = FOP_UNSIGNED_OFFSET,
}; };
static int environ_open(struct inode *inode, struct file *file) static int environ_open(struct inode *inode, struct file *file)

View File

@ -36,7 +36,7 @@ EXPORT_SYMBOL(generic_ro_fops);
static inline bool unsigned_offsets(struct file *file) static inline bool unsigned_offsets(struct file *file)
{ {
return file->f_mode & FMODE_UNSIGNED_OFFSET; return file->f_op->fop_flags & FOP_UNSIGNED_OFFSET;
} }
/** /**

View File

@ -28,7 +28,8 @@
.poll = drm_poll,\ .poll = drm_poll,\
.read = drm_read,\ .read = drm_read,\
.llseek = noop_llseek, \ .llseek = noop_llseek, \
.mmap = drm_gem_mmap .mmap = drm_gem_mmap, \
.fop_flags = FOP_UNSIGNED_OFFSET
/** /**
* DEFINE_DRM_ACCEL_FOPS() - macro to generate file operations for accelerators drivers * DEFINE_DRM_ACCEL_FOPS() - macro to generate file operations for accelerators drivers

View File

@ -447,7 +447,8 @@ struct drm_gem_object {
.poll = drm_poll,\ .poll = drm_poll,\
.read = drm_read,\ .read = drm_read,\
.llseek = noop_llseek,\ .llseek = noop_llseek,\
.mmap = drm_gem_mmap .mmap = drm_gem_mmap, \
.fop_flags = FOP_UNSIGNED_OFFSET
/** /**
* DEFINE_DRM_GEM_FOPS() - macro to generate file operations for GEM drivers * DEFINE_DRM_GEM_FOPS() - macro to generate file operations for GEM drivers

View File

@ -267,6 +267,7 @@ unsigned long drm_gem_dma_get_unmapped_area(struct file *filp,
.read = drm_read,\ .read = drm_read,\
.llseek = noop_llseek,\ .llseek = noop_llseek,\
.mmap = drm_gem_mmap,\ .mmap = drm_gem_mmap,\
.fop_flags = FOP_UNSIGNED_OFFSET, \
DRM_GEM_DMA_UNMAPPED_AREA_FOPS \ DRM_GEM_DMA_UNMAPPED_AREA_FOPS \
} }

View File

@ -146,8 +146,7 @@ typedef int (dio_iodone_t)(struct kiocb *iocb, loff_t offset,
/* Expect random access pattern */ /* Expect random access pattern */
#define FMODE_RANDOM ((__force fmode_t)(1 << 12)) #define FMODE_RANDOM ((__force fmode_t)(1 << 12))
/* File is huge (eg. /dev/mem): treat loff_t as unsigned */ /* FMODE_* bit 13 */
#define FMODE_UNSIGNED_OFFSET ((__force fmode_t)(1 << 13))
/* File is opened with O_PATH; almost nothing can be done with it */ /* File is opened with O_PATH; almost nothing can be done with it */
#define FMODE_PATH ((__force fmode_t)(1 << 14)) #define FMODE_PATH ((__force fmode_t)(1 << 14))
@ -2073,6 +2072,8 @@ struct file_operations {
#define FOP_DIO_PARALLEL_WRITE ((__force fop_flags_t)(1 << 3)) #define FOP_DIO_PARALLEL_WRITE ((__force fop_flags_t)(1 << 3))
/* Contains huge pages */ /* Contains huge pages */
#define FOP_HUGE_PAGES ((__force fop_flags_t)(1 << 4)) #define FOP_HUGE_PAGES ((__force fop_flags_t)(1 << 4))
/* Treat loff_t as unsigned (e.g., /dev/mem) */
#define FOP_UNSIGNED_OFFSET ((__force fop_flags_t)(1 << 5))
/* Wrap a directory iterator that needs exclusive inode access */ /* Wrap a directory iterator that needs exclusive inode access */
int wrap_directory_iterator(struct file *, struct dir_context *, int wrap_directory_iterator(struct file *, struct dir_context *,

View File

@ -1229,7 +1229,7 @@ static inline u64 file_mmap_size_max(struct file *file, struct inode *inode)
return MAX_LFS_FILESIZE; return MAX_LFS_FILESIZE;
/* Special "we do even unsigned file positions" case */ /* Special "we do even unsigned file positions" case */
if (file->f_mode & FMODE_UNSIGNED_OFFSET) if (file->f_op->fop_flags & FOP_UNSIGNED_OFFSET)
return 0; return 0;
/* Yes, random drivers might want more. But I'm tired of buggy drivers */ /* Yes, random drivers might want more. But I'm tired of buggy drivers */