/* * decide whether a page can be released, possibly by cancelling a store to it * - we're allowed to sleep if __GFP_DIRECT_RECLAIM is flagged */ bool __fscache_maybe_release_page(struct fscache_cookie *cookie, struct page *page, gfp_t gfp) { struct page *xpage; void *val; _enter("%p,%p,%x", cookie, page, gfp); try_again: rcu_read_lock(); val = radix_tree_lookup(&cookie->stores, page->index); if (!val) { rcu_read_unlock(); fscache_stat(&fscache_n_store_vmscan_not_storing); __fscache_uncache_page(cookie, page); return true; } /* see if the page is actually undergoing storage - if so we can't get * rid of it till the cache has finished with it */ if (radix_tree_tag_get(&cookie->stores, page->index, FSCACHE_COOKIE_STORING_TAG)) { rcu_read_unlock(); goto page_busy; } /* the page is pending storage, so we attempt to cancel the store and * discard the store request so that the page can be reclaimed */ spin_lock(&cookie->stores_lock); rcu_read_unlock(); if (radix_tree_tag_get(&cookie->stores, page->index, FSCACHE_COOKIE_STORING_TAG)) { /* the page started to undergo storage whilst we were looking, * so now we can only wait or return */ spin_unlock(&cookie->stores_lock); goto page_busy; } xpage = radix_tree_delete(&cookie->stores, page->index); spin_unlock(&cookie->stores_lock); if (xpage) { fscache_stat(&fscache_n_store_vmscan_cancelled); fscache_stat(&fscache_n_store_radix_deletes); ASSERTCMP(xpage, ==, page); } else {
bool __fscache_maybe_release_page(struct fscache_cookie *cookie, struct page *page, gfp_t gfp) { struct page *xpage; void *val; _enter("%p,%p,%x", cookie, page, gfp); rcu_read_lock(); val = radix_tree_lookup(&cookie->stores, page->index); if (!val) { rcu_read_unlock(); fscache_stat(&fscache_n_store_vmscan_not_storing); __fscache_uncache_page(cookie, page); return true; } /* */ if (radix_tree_tag_get(&cookie->stores, page->index, FSCACHE_COOKIE_STORING_TAG)) { rcu_read_unlock(); goto page_busy; } /* */ spin_lock(&cookie->stores_lock); rcu_read_unlock(); if (radix_tree_tag_get(&cookie->stores, page->index, FSCACHE_COOKIE_STORING_TAG)) { /* */ spin_unlock(&cookie->stores_lock); goto page_busy; } xpage = radix_tree_delete(&cookie->stores, page->index); spin_unlock(&cookie->stores_lock); if (xpage) { fscache_stat(&fscache_n_store_vmscan_cancelled); fscache_stat(&fscache_n_store_radix_deletes); ASSERTCMP(xpage, ==, page); } else {