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
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel

Reply via email to