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