在 2020/1/17 上午5:52, Johannes Weiner 写道: > You simply cannot serialize on page->mem_cgroup->lruvec when > page->mem_cgroup isn't stable. You need to serialize on the page > itself, one way or another, to make this work. > > > So here is a crazy idea that may be worth exploring: > > Right now, pgdat->lru_lock protects both PageLRU *and* the lruvec's > linked list. > > Can we make PageLRU atomic and use it to stabilize the lru_lock > instead, and then use the lru_lock only serialize list operations? > Hi Johannes, I am trying to figure out the solution of atomic PageLRU, but is blocked by the following sitations, when PageLRU and lru list was protected together under lru_lock, the PageLRU could be a indicator if page on lru list But now seems it can't be the indicator anymore. Could you give more clues of stabilization usage of PageLRU? __page_cache_release/release_pages/compaction __pagevec_lru_add if (TestClearPageLRU(page)) if (!PageLRU()) lruvec_lock(); list_add(); lruvec_unlock(); SetPageLRU() //position 1 lock_page_lruvec_irqsave(page, &flags); del_page_from_lru_list(page, lruvec, ..); unlock_page_lruvec_irqrestore(lruvec, flags); SetPageLRU() //position 2 Thanks a lot! Alex > I.e. in compaction, you'd do > > if (!TestClearPageLRU(page)) > goto isolate_fail; > /* > * We isolated the page's LRU state and thereby locked out all > * other isolators, including cgroup page moving, page reclaim, > * page freeing etc. That means page->mem_cgroup is now stable > * and we can safely look up the correct lruvec and take the > * page off its physical LRU list. > */ > lruvec = mem_cgroup_page_lruvec(page); > spin_lock_irq(&lruvec->lru_lock); > del_page_from_lru_list(page, lruvec, page_lru(page)); > > Putback would mostly remain the same (although you could take the > PageLRU setting out of the list update locked section, as long as it's > set after the page is physically linked): > > /* LRU isolation pins page->mem_cgroup */ > lruvec = mem_cgroup_page_lruvec(page) > spin_lock_irq(&lruvec->lru_lock); > add_page_to_lru_list(...); > spin_unlock_irq(&lruvec->lru_lock); > > SetPageLRU(page); > > And you'd have to carefully review and rework other sites that rely on > PageLRU: reclaim, __page_cache_release(), __activate_page() etc. > > Especially things like activate_page(), which used to only check > PageLRU to shuffle the page on the LRU list would now have to briefly > clear PageLRU and then set it again afterwards. > > However, aside from a bit more churn in those cases, and the > unfortunate additional atomic operations, I currently can't think of a > fundamental reason why this wouldn't work. > > Hugh, what do you think? >