fs: move FMODE_UNSIGNED_OFFSET to fop_flags
authorChristian Brauner <brauner@kernel.org>
Fri, 9 Aug 2024 10:38:56 +0000 (12:38 +0200)
committerChristian Brauner <brauner@kernel.org>
Fri, 30 Aug 2024 06:22:36 +0000 (08:22 +0200)
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>
18 files changed:
drivers/char/adi.c
drivers/char/mem.c
drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
drivers/gpu/drm/drm_file.c
drivers/gpu/drm/gma500/psb_drv.c
drivers/gpu/drm/i915/i915_driver.c
drivers/gpu/drm/nouveau/nouveau_drm.c
drivers/gpu/drm/radeon/radeon_drv.c
drivers/gpu/drm/tegra/drm.c
drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
drivers/gpu/drm/xe/xe_device.c
fs/proc/base.c
fs/read_write.c
include/drm/drm_accel.h
include/drm/drm_gem.h
include/drm/drm_gem_dma_helper.h
include/linux/fs.h
mm/mmap.c

index 751d7cc0da1b3be2beca3f362e3a316a7d35b33c..1c76c8758f0f8ed795b196cbac7a4943216277ed 100644 (file)
 
 #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)
 {
        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 = {
        .owner          = THIS_MODULE,
        .llseek         = adi_llseek,
-       .open           = adi_open,
        .read           = adi_read,
        .write          = adi_write,
+       .fop_flags      = FOP_UNSIGNED_OFFSET,
 };
 
 static struct miscdevice adi_miscdev = {
index 7c359cc406d5bc230531f6a1470e4883fe0f1d06..169eed162a7fba2e8357efc01520fe750b7577f2 100644 (file)
@@ -643,6 +643,7 @@ static const struct file_operations __maybe_unused mem_fops = {
        .get_unmapped_area = get_unmapped_area_mem,
        .mmap_capabilities = memory_mmap_capabilities,
 #endif
+       .fop_flags      = FOP_UNSIGNED_OFFSET,
 };
 
 static const struct file_operations null_fops = {
@@ -693,7 +694,7 @@ static const struct memdev {
        umode_t mode;
 } devlist[] = {
 #ifdef CONFIG_DEVMEM
-       [DEVMEM_MINOR] = { "mem", &mem_fops, FMODE_UNSIGNED_OFFSET, 0 },
+       [DEVMEM_MINOR] = { "mem", &mem_fops, 0, 0 },
 #endif
        [3] = { "null", &null_fops, FMODE_NOWAIT, 0666 },
 #ifdef CONFIG_DEVPORT
index 094498a0964b510a8e561c32b531fee277ab569d..d7ef8cbecf6c109994462c62e9fe90eeb91bb092 100644 (file)
@@ -2908,6 +2908,7 @@ static const struct file_operations amdgpu_driver_kms_fops = {
 #ifdef CONFIG_PROC_FS
        .show_fdinfo = drm_show_fdinfo,
 #endif
+       .fop_flags = FOP_UNSIGNED_OFFSET,
 };
 
 int amdgpu_file_to_fpriv(struct file *filp, struct amdgpu_fpriv **fpriv)
index 714e42b05108007e26eb08eb0eaf11d74761a83f..f8de3cba1a08710a71624f13b3ed8d91a6d98269 100644 (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 &&
            dev->switch_power_state != DRM_SWITCH_POWER_DYNAMIC_OFF)
                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",
                     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->f_mode |= FMODE_UNSIGNED_OFFSET;
        priv->filp = filp;
 
        mutex_lock(&dev->filelist_mutex);
index 8b64f61ffaf9d578800c701c3130759085e09d37..d67c2b3ad901165d917c13d8d6e621f5399ed60b 100644 (file)
@@ -498,6 +498,7 @@ static const struct file_operations psb_gem_fops = {
        .mmap = drm_gem_mmap,
        .poll = drm_poll,
        .read = drm_read,
+       .fop_flags = FOP_UNSIGNED_OFFSET,
 };
 
 static const struct drm_driver driver = {
index fb8e9c2fcea5317ae52fec6b4e6e53034425987e..cf276299bccbc9634cb1f525b6bed977d6a2332a 100644 (file)
@@ -1671,6 +1671,7 @@ static const struct file_operations i915_driver_fops = {
 #ifdef CONFIG_PROC_FS
        .show_fdinfo = drm_show_fdinfo,
 #endif
+       .fop_flags = FOP_UNSIGNED_OFFSET,
 };
 
 static int
index a58c31089613ebc67076937885e20bee1c54bda8..e243b42f85826cdc14b5a0130b8e8f5f1604f63c 100644 (file)
@@ -1274,6 +1274,7 @@ nouveau_driver_fops = {
        .compat_ioctl = nouveau_compat_ioctl,
 #endif
        .llseek = noop_llseek,
+       .fop_flags = FOP_UNSIGNED_OFFSET,
 };
 
 static struct drm_driver
index 7bf08164140ef7ae95af002c8193b62996745ff9..ac49779ed03d106c7265b62c6794b9b55160fbf8 100644 (file)
@@ -520,6 +520,7 @@ static const struct file_operations radeon_driver_kms_fops = {
 #ifdef CONFIG_COMPAT
        .compat_ioctl = radeon_kms_compat_ioctl,
 #endif
+       .fop_flags = FOP_UNSIGNED_OFFSET,
 };
 
 static const struct drm_ioctl_desc radeon_ioctls_kms[] = {
index 03d1c76aec2d3f7aca6a52acbb1a42455b37faa8..108c26a33edb35a0aea554fc75678dc0ccecc5fc 100644 (file)
@@ -801,6 +801,7 @@ static const struct file_operations tegra_drm_fops = {
        .read = drm_read,
        .compat_ioctl = drm_compat_ioctl,
        .llseek = noop_llseek,
+       .fop_flags = FOP_UNSIGNED_OFFSET,
 };
 
 static int tegra_drm_context_cleanup(int id, void *p, void *data)
index 50ad3105c16eba699e92f4610d0e90f3d40ef4ae..2825dd3149ed5cbafa0e30c7986529c55f603f77 100644 (file)
@@ -1609,6 +1609,7 @@ static const struct file_operations vmwgfx_driver_fops = {
        .compat_ioctl = vmw_compat_ioctl,
 #endif
        .llseek = noop_llseek,
+       .fop_flags = FOP_UNSIGNED_OFFSET,
 };
 
 static const struct drm_driver driver = {
index f2f1d8ddb22138cb0e04df0635b01478b6a14bb2..2e5537d6608d51619871150c2bed7cd9bc248805 100644 (file)
@@ -238,6 +238,7 @@ static const struct file_operations xe_driver_fops = {
 #ifdef CONFIG_PROC_FS
        .show_fdinfo = drm_show_fdinfo,
 #endif
+       .fop_flags = FOP_UNSIGNED_OFFSET,
 };
 
 static struct drm_driver driver = {
index 72a1acd03675cc77da7320a14426f40e6fc9513f..1409d1003101cf7a6103005511ed6ac56173e248 100644 (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)
 {
-       int ret = __mem_open(inode, file, PTRACE_MODE_ATTACH);
-
-       /* OK to pass negative loff_t, we can catch out-of-range */
-       file->f_mode |= FMODE_UNSIGNED_OFFSET;
-
-       return ret;
+       if (WARN_ON_ONCE(!(file->f_op->fop_flags & FOP_UNSIGNED_OFFSET)))
+               return -EINVAL;
+       return __mem_open(inode, file, PTRACE_MODE_ATTACH);
 }
 
 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,
        .open           = mem_open,
        .release        = mem_release,
+       .fop_flags      = FOP_UNSIGNED_OFFSET,
 };
 
 static int environ_open(struct inode *inode, struct file *file)
index 90e283b31ca18195ff8c6a5cc4becbaa333d9f91..89d4af0e3b93d3172c8ad18b140271382f788683 100644 (file)
@@ -36,7 +36,7 @@ EXPORT_SYMBOL(generic_ro_fops);
 
 static inline bool unsigned_offsets(struct file *file)
 {
-       return file->f_mode & FMODE_UNSIGNED_OFFSET;
+       return file->f_op->fop_flags & FOP_UNSIGNED_OFFSET;
 }
 
 /**
index f4d3784b1dce0572a974e3924c31b90db4540ad8..41c78b7d712cc112e631c4b4ad89788d312c8691 100644 (file)
@@ -28,7 +28,8 @@
        .poll           = drm_poll,\
        .read           = drm_read,\
        .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
index bae4865b2101ae4467b6253cb95fbb6966e0acdb..d8b86df2ec0dabe4135aca74f942fb4fb01441b3 100644 (file)
@@ -447,7 +447,8 @@ struct drm_gem_object {
        .poll           = drm_poll,\
        .read           = drm_read,\
        .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
index a827bde494f610fe9afa03229cd5001f852a01e8..f2678e7ecb9847917e9c6c0287af9815d54bae79 100644 (file)
@@ -267,6 +267,7 @@ unsigned long drm_gem_dma_get_unmapped_area(struct file *filp,
                .read           = drm_read,\
                .llseek         = noop_llseek,\
                .mmap           = drm_gem_mmap,\
+               .fop_flags = FOP_UNSIGNED_OFFSET, \
                DRM_GEM_DMA_UNMAPPED_AREA_FOPS \
        }
 
index 696c620f90e0bd0605f86b5896d84d6ca38b1624..0145bda465ff02e4e27519e627e630ac8b14ba6a 100644 (file)
@@ -146,8 +146,7 @@ typedef int (dio_iodone_t)(struct kiocb *iocb, loff_t offset,
 /* Expect random access pattern */
 #define FMODE_RANDOM           ((__force fmode_t)(1 << 12))
 
-/* File is huge (eg. /dev/mem): treat loff_t as unsigned */
-#define FMODE_UNSIGNED_OFFSET  ((__force fmode_t)(1 << 13))
+/* FMODE_* bit 13 */
 
 /* File is opened with O_PATH; almost nothing can be done with it */
 #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))
 /* Contains huge pages */
 #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 */
 int wrap_directory_iterator(struct file *, struct dir_context *,
index d0dfc85b209bbc4113376bb894756e727b676f6e..6ddb278a5ee861d9373acb6b4eaf217cae882b1e 100644 (file)
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -1229,7 +1229,7 @@ static inline u64 file_mmap_size_max(struct file *file, struct inode *inode)
                return MAX_LFS_FILESIZE;
 
        /* 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;
 
        /* Yes, random drivers might want more. But I'm tired of buggy drivers */