On Sat, Apr 14, 2018 at 07:12:31AM -0700, Matthew Wilcox wrote:
> - xa_lock_irq(&mapping->i_pages);
> - error = page_cache_tree_insert(mapping, page, shadowp);
> - radix_tree_preload_end();
> - if (unlikely(error))
> - goto err_insert;
> + do {
> + xas_lock_irq(&xas);
> + old = xas_create(&xas);
> + if (xas_error(&xas))
> + goto unlock;
> + if (xa_is_value(old)) {
> + mapping->nrexceptional--;
> + if (shadowp)
> + *shadowp = old;
> + } else if (old) {
> + xas_set_err(&xas, -EEXIST);
> + goto unlock;
> + }
> +
> + xas_store(&xas, page);
> + mapping->nrpages++;
At LSFMM, I was unable to explain in the moment why I was doing
xas_create() followed by xas_store(), rather than just calling
xas_store(). Looking at this code on my laptop, it was immediately
obvious to me -- the semantics of attempting to insert a page into the
page cache when there's already one there is to return -EEXIST.
We could also write this function this way:
+ old = xas_load(&xas);
+ if (old && !xa_is_value(old))
+ xas_set_err(&xas, -EEXIST);
+ xas_store(&xas, page);
+ if (xas_error(&xas))
+ goto unlock;
+ if (old) {
+ mapping->nrexceptional--;
+ if (shadowp)
+ *shadowp = old;
+ }
+ mapping->nrpages++;
which I think is slightly clearer. Or for those allergic to gotos, the
entire function could look like (option 3):
+ do {
+ xas_lock_irq(&xas);
+ old = xas_load(&xas);
+ if (old && !xa_is_value(old))
+ xas_set_err(&xas, -EEXIST);
+ xas_store(&xas, page);
+
+ if (!xas_error(&xas)) {
+ if (old) {
+ mapping->nrexceptional--;
+ if (shadowp)
+ *shadowp = old;
+ }
+ mapping->nrpages++;
+
+ /*
+ * hugetlb pages do not participate in
+ * page cache accounting.
+ */
+ if (!huge)
+ __inc_node_page_state(page, NR_FILE_PAGES);
+ }
+ xas_unlock_irq(&xas);
+ } while (xas_nomem(&xas, gfp_mask & ~__GFP_HIGHMEM));
------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
Linux-f2fs-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel