On 9/11/19 8:54 AM, Michal Hocko wrote: > On Wed 11-09-19 14:42:41, David Hildenbrand wrote: >> On 11.09.19 14:25, Michal Hocko wrote: >>> On Wed 11-09-19 14:19:41, Michal Hocko wrote: >>>> On Wed 11-09-19 08:08:38, Michael S. Tsirkin wrote: >>>>> On Wed, Sep 11, 2019 at 01:36:19PM +0200, Michal Hocko wrote: >>>>>> On Tue 10-09-19 14:23:40, Alexander Duyck wrote: >>>>>> [...] >>>>>>> We don't put any limitations on the allocator other then that it needs to >>>>>>> clean up the metadata on allocation, and that it cannot allocate a page >>>>>>> that is in the process of being reported since we pulled it from the >>>>>>> free_list. If the page is a "Reported" page then it decrements the >>>>>>> reported_pages count for the free_area and makes sure the page doesn't >>>>>>> exist in the "Boundary" array pointer value, if it does it moves the >>>>>>> "Boundary" since it is pulling the page. >>>>>> This is still a non-trivial limitation on the page allocation from an >>>>>> external code IMHO. I cannot give any explicit reason why an ordering on >>>>>> the free list might matter (well except for page shuffling which uses it >>>>>> to make physical memory pattern allocation more random) but the >>>>>> architecture seems hacky and dubious to be honest. It shoulds like the >>>>>> whole interface has been developed around a very particular and single >>>>>> purpose optimization. >>>>>> >>>>>> I remember that there was an attempt to report free memory that provided >>>>>> a callback mechanism [1], which was much less intrusive to the internals >>>>>> of the allocator yet it should provide a similar functionality. Did you >>>>>> see that approach? How does this compares to it? Or am I completely off >>>>>> when comparing them? >>>>>> >>>>>> [1] mostly likely not the latest version of the patchset >>>>>> http://lkml.kernel.org/r/1502940416-42944-5-git-send-email-wei.w.wang@xxxxxxxxx >>>>> Linus nacked that one. He thinks invoking callbacks with lots of >>>>> internal mm locks is too fragile. >>>> I would be really curious how much he would be happy about injecting >>>> other restrictions on the allocator like this patch proposes. This is >>>> more intrusive as it has a higher maintenance cost longterm IMHO. >>> Btw. I do agree that callbacks with internal mm locks are not great >>> either. We do have a model for that in mmu_notifiers and it is something >>> I do consider PITA, on the other hand it is mostly sleepable part of the >>> interface which makes it the real pain. The above callback mechanism was >>> explicitly documented with restrictions and that the context is >>> essentially atomic with no access to particular struct pages and no >>> expensive operations possible. So in the end I've considered it >>> acceptably painful. Not that I want to override Linus' nack but if >>> virtualization usecases really require some form of reporting and no >>> other way to do that push people to invent even more interesting >>> approaches then we should simply give them/you something reasonable >>> and least intrusive to our internals. >>> >> The issue with "[PATCH v14 4/5] mm: support reporting free page blocks" >> is that it cannot really handle the use case we have here if I am not >> wrong. While a page is getting processed by the hypervisor (e.g. >> MADV_DONTNEED), it must not get reused. > What prevents to use the callback to get a list of pfn ranges to work on > and then use something like start_isolate_page_range on the collected > pfn ranges to make sure nobody steals pages from under your feet, do > your thing and drop the isolated state afterwards. > In my series, I am doing something similar. - Track (MAX_ORDER - 2) free pages in bitmap maintained on a per-zone basis. - Use __isolate_free_page on the pages marked in the bitmap and are still free. - Report chunks of 16 isolated pages to the hypervisor. - Return them back to the buddy once the request is processed. > I am saying somethig like because you wouldn't really want a generic > has_unmovable_pages but rather > if (!page_ref_count(page)) { > if (PageBuddy(page)) > iter += (1 << page_order(page)) - 1; > continue; > } > subset of it. -- Thanks Nitesh