Sorry for late reply.
On 2024/10/28 17:48, David Hildenbrand wrote:
On 25.10.24 22:21, David Hildenbrand wrote:
Sorry for the late reply!
IMHO, as I discussed with Kirill, we still need maintain
compatibility
with the 'huge=' mount option. This means that if 'huge=never' is
set
for tmpfs, huge page allocation will still be prohibited (which can
address Hugh's request?). However, if 'huge=' is not set, we can
allocate large folios based on the write size.
So, in order to make tmpfs behave like other filesystems, we need to
allocate large folios by default. Not setting 'huge=' is the same as
setting it to 'huge=never' as per documentation. But 'huge=' is meant to
control THP, not large folios, so it should not have a conflict here, or
else, what case are you thinking?
I think we really have to move away from "huge/thp == PMD", that's a
historical artifact. Everything else will simply be inconsistent and
confusing in the future -- and I don't see any real need for that. For
anonymous memory and anon shmem we managed the transition. (there is a
longer writeup from me about this topic, so I won't go into detail).
I think I raised this in the past, but tmpfs/shmem is just like any
other file system .. except it sometimes really isn't and behaves much
more like (swappable) anonymous memory. (or mlocked files)
There are many systems out there that run without swap enabled, or with
extremely minimal swap (IIRC until recently kubernetes was completely
incompatible with swapping). Swap can even be disabled today for shmem
using a mount option.
That's a big difference to all other file systems where you are
guaranteed to have backend storage where you can simply evict under
memory pressure (might temporarily fail, of course).
I *think* that's the reason why we have the "huge=" parameter that also
controls the THP allocations during page faults (IOW possible memory
over-allocation). Maybe also because it was a new feature, and we only
had a single THP size.
There is, of course also the "fallocate() might not free up memory if
there is an unexpected reference on the page because splitting it will
fail" problem, that even exists when not over-allocating memory in the
first place ...
So ...I don't think tmpfs behaves like other file system in some cases.
And I don't think ignoring these points is a good idea.
Fortunately I don't maintain that code :)
If we don't want to go with the shmem_enabled toggles, we should
probably still extend the documentation to cover "all THP sizes", like
we did elsewhere.
huge=never: no THPs of any size
huge=always: THPs of any size (fault/write/etc)
huge=fadvise: like "always" but only with fadvise/madvise
huge=within_size: like "fadvise" but respect i_size
Thinking some more about that over the weekend, this is likely the way
to go, paired with conditionally changing the default to
always/within_size. I suggest a kconfig option for that.
I am still worried about adding a new kconfig option, which might
complicate the tmpfs controls further.
That should probably do as a first shot; I assume people will want more
control over which size to use, especially during page faults, but that
can likely be added later.
After some discussions, I think the first step is to achieve two goals:
1) Try to make tmpfs use large folios like other file systems, that
means we should avoid adding more complex control options (per Matthew).
2) Still need maintain compatibility with the 'huge=' mount option (per
Kirill), as I also remembered we have customers who use
'huge=within_size' to allocate THPs for better performance.
Based on these considerations, my first step is to neither add a new
'huge=' option parameter nor introduce the mTHP interfaces control for
tmpfs, but rather to change the default huge allocation behavior for
tmpfs. That is to say, when 'huge=' option is not configured, we will
allow the huge folios allocation based on the write size. As a result,
the behavior of huge pages for tmpfs will change as follows:
no 'huge=' set: can allocate any size huge folios based on write size
huge=never: no any size huge folios
huge=always: only PMD sized THP allocation as before
huge=fadvise: like "always" but only with fadvise/madvise
huge=within_size: like "fadvise" but respect i_size
The next step is to continue discussing whether to add a new Kconfig
option or FADV_* in the future.
So what do you think?