On Wed, Sep 30, 2020 at 12:35:57PM +0200, Michal Hocko wrote: > On Wed 30-09-20 00:07:42, Uladzislau Rezki wrote: > [...] > > <snip> > > bool is_pcp_cache_empty(gfp_t gfp) > > { > > struct per_cpu_pages *pcp; > > struct zoneref *ref; > > unsigned long flags; > > bool empty; > > > > ref = first_zones_zonelist(node_zonelist( > > numa_node_id(), gfp), gfp_zone(gfp), NULL); > > if (!ref->zone) > > return true; > > > > local_irq_save(flags); > > pcp = &this_cpu_ptr(ref->zone->pageset)->pcp; > > empty = list_empty(&pcp->lists[gfp_migratetype(gfp)]); > > local_irq_restore(flags); > > > > return empty; > > } > > > > disable_irq(); > > if (!is_pcp_cache_empty(GFP_NOWAIT)) > > __get_free_page(GFP_NOWAIT); > > enable_irq(); > > <snip> > > > > Do you mean to have something like above? I mean some extra API > > function that returns true or false if fast-fast allocation can > > either occur or not. Above code works just fine and never touches > > main zone->lock. > > The above code works with the _current_ implementation and it restricts > its implementation to some degree. Future changes might get harder to > implement with a pattern like this. I do not think we want users to be > aware of internal implementation details like pcp caches, migrate types > or others. While pcp caches are here for years and unlikely to change in > a foreseeable future many details are changing on regular basis. > I see your view. That was en example for better understanding. Thanks. -- Vlad Rezki