On Thu, May 21, 2026, at 09:09, Dan Carpenter wrote:
> Is there a point to FOP_UNSIGNED_OFFSET now that everyone is on 64bit?
> I thought the flag was for back in the day where we it was a huge deal
> to access 4GB instead of 2GB.
>
> It's mostly used in DRM.  drm_open_helper() forces you to set the flag
> but drm_read() ignores the offset so I don't understand the point of
> this.

As far as I understand it, this is needed specifically for
character devices with an mmap() file operation that encodes
information in the high offset bits, see be83bbf80682 ("mmap:
introduce sane default mmap limits").

For /dev/kmem, this is is needed to access the actual kernel
memory on architectures that map it to negative addresses,
and this one actually does llseek/read/write up to U64_MAX,
which would be useful on 32-bit compat tasks reading 64-bit
kernel memory, and we could probably just not do that.

For the mmap() interface, I see that things are a bit messy
in multiple ways:

- DRM drivers on 32-bit kernels need this to mmap() GEM
  buffer objects that have a file offset just above
  ULONG_MAX, which is the limit in file_mmap_size_max()
  for character devices. 
  As you pointed out, llseek/read/write does not have this
  limit.

- mmap2() can never map up to ULLONG_MAX even with the flag,
  but is in practice limited to 2^44 (ULONG_MAX << 12)
  when FOP_UNSIGNED_OFFSET is set.

- compat_mmap() checks against the 64-bit MAX_LFS_FILESIZE
  and ULONG_MAX in file_mmap_ok(), so it's actually able
  to map beyond these limits. I suppose this is not a
  bug itself, but is unexpected.

- MAX_LFS_FILESIZE itself is defined as
  "((loff_t)ULONG_MAX << PAGE_SHIFT)" on 32-bit systems,
  but mmap2() actually uses a fixed 12 bit shift
  rather than PAGE_SHIFT on most architectures with
  a compile-time page size choice.

       Arnd

Reply via email to