Re: [PATCH v6 01/27] mm: Introduce struct folio

Kirill A. Shutemov
2021-04-06T12:29:40Z

On Wed, Mar 31, 2021 at 07:47:02PM +0100, Matthew Wilcox (Oracle) wrote:
> +/**
> + * folio_next - Move to the next physical folio.
> + * @folio: The folio we're currently operating on.
> + *
> + * If you have physically contiguous memory which may span more than
> + * one folio (eg a &struct bio_vec), use this function to move from one
> + * folio to the next. Do not use it if the memory is only virtually
> + * contiguous as the folios are almost certainly not adjacent to each
> + * other. This is the folio equivalent to writing ``page++``.
> + *
> + * Context: We assume that the folios are refcounted and/or locked at a
> + * higher level and do not adjust the reference counts.
> + * Return: The next struct folio.
> + */
> +static inline struct folio *folio_next(struct folio *folio)
> +{
> +#if defined(CONFIG_SPARSEMEM) && !defined(CONFIG_SPARSEMEM_VMEMMAP)
> + return (struct folio *)nth_page(&folio->page, folio_nr_pages(folio));
> +#else
> + return folio + folio_nr_pages(folio);
> +#endif

Do we really need the #if here?

From quick look at nth_page() and memory_model.h, compiler should be able
to simplify calculation for FLATMEM or SPARSEMEM_VMEMMAP to what you do in
the #else. No?

> @@ -224,6 +224,71 @@ struct page {
> #endif
> } _struct_page_alignment;
>
> +/**
> + * struct folio - Represents a contiguous set of bytes.
> + * @flags: Identical to the page flags.
> + * @lru: Least Recently Used list; tracks how recently this folio was used.
> + * @mapping: The file this page belongs to, or refers to the anon_vma for
> + * anonymous pages.
> + * @index: Offset within the file, in units of pages. For anonymous pages,
> + * this is the index from the beginning of the mmap.
> + * @private: Filesystem per-folio data (see attach_folio_private()).
> + * Used for swp_entry_t if FolioSwapCache().
> + * @_mapcount: How many times this folio is mapped to userspace. Use
> + * folio_mapcount() to access it.
> + * @_refcount: Number of references to this folio. Use folio_ref_count()
> + * to read it.
> + * @memcg_data: Memory Control Group data.
> + *
> + * A folio is a physically, virtually and logically contiguous set
> + * of bytes. It is a power-of-two in size, and it is aligned to that
> + * same power-of-two. It is at least as large as %PAGE_SIZE. If it is
> + * in the page cache, it is at a file offset which is a multiple of that
> + * power-of-two.
> + */
> +struct folio {
> + /* private: don't document the anon union */
> + union {
> + struct {
> + /* public: */
> + unsigned long flags;
> + struct list_head lru;
> + struct address_space *mapping;
> + pgoff_t index;
> + unsigned long private;
> + atomic_t _mapcount;
> + atomic_t _refcount;
> +#ifdef CONFIG_MEMCG
> + unsigned long memcg_data;
> +#endif

As Christoph, I'm not a fan of this :/

> + /* private: the union with struct page is transitional */
> + };
> + struct page page;
> + };
> +};

--
Kirill A. Shutemov