Skip to content

Commit

Permalink
fs: Allow fine-grained control of folio sizes
Browse files Browse the repository at this point in the history
Some filesystems want to be able to limit the maximum size of folios,
and some want to be able to ensure that folios are at least a certain
size.  Add mapping_set_folio_orders() to allow this level of control.
The max folio order parameter is ignored and it is always set to
MAX_PAGECACHE_ORDER.

[Pankaj]: added mapping_min_folio_order(), changed MAX_MASK to 0x0003e000
Signed-off-by: Pankaj Raghav <p.raghav@samsung.com>
[mcgrof: rebase in light of "mm, netfs, fscache: stop read optimisation
when folio removed from pagecache" which adds AS_RELEASE_ALWAYS]
Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
  • Loading branch information
Matthew Wilcox (Oracle) authored and Panky-codes committed Oct 11, 2023
1 parent 94f6f05 commit 27f85d8
Showing 1 changed file with 67 additions and 18 deletions.
85 changes: 67 additions & 18 deletions include/linux/pagemap.h
Original file line number Diff line number Diff line change
Expand Up @@ -202,10 +202,16 @@ enum mapping_flags {
AS_EXITING = 4, /* final truncate in progress */
/* writeback related tags are not used */
AS_NO_WRITEBACK_TAGS = 5,
AS_LARGE_FOLIO_SUPPORT = 6,
AS_RELEASE_ALWAYS, /* Call ->release_folio(), even if no private data */
AS_RELEASE_ALWAYS = 6, /* Call ->release_folio(), even if no private data */
AS_FOLIO_ORDER_MIN = 8,
AS_FOLIO_ORDER_MAX = 13,
/* 8-17 are used for FOLIO_ORDER */
};

#define AS_FOLIO_ORDER_MIN_MASK 0x00001f00
#define AS_FOLIO_ORDER_MAX_MASK 0x0003e000
#define AS_FOLIO_ORDER_MASK (AS_FOLIO_ORDER_MIN_MASK | AS_FOLIO_ORDER_MAX_MASK)

/**
* mapping_set_error - record a writeback error in the address_space
* @mapping: the mapping in which an error should be set
Expand Down Expand Up @@ -310,6 +316,53 @@ static inline void mapping_set_gfp_mask(struct address_space *m, gfp_t mask)
m->gfp_mask = mask;
}

/*
* There are some parts of the kernel which assume that PMD entries
* are exactly HPAGE_PMD_ORDER. Those should be fixed, but until then,
* limit the maximum allocation order to PMD size. I'm not aware of any
* assumptions about maximum order if THP are disabled, but 8 seems like
* a good order (that's 1MB if you're using 4kB pages)
*/
#ifdef CONFIG_TRANSPARENT_HUGEPAGE
#define MAX_PAGECACHE_ORDER HPAGE_PMD_ORDER
#else
#define MAX_PAGECACHE_ORDER 8
#endif

/*
* mapping_set_folio_orders() - Set the range of folio sizes supported.
* @mapping: The file.
* @min: Minimum folio order (between 0-MAX_PAGECACHE_ORDER inclusive).
* @max: Maximum folio order (between 0-MAX_PAGECACHE_ORDER inclusive).
*
* The filesystem should call this function in its inode constructor to
* indicate which sizes of folio the VFS can use to cache the contents
* of the file. This should only be used if the filesystem needs special
* handling of folio sizes (ie there is something the core cannot know).
* Do not tune it based on, eg, i_size.
*
* Context: This should not be called while the inode is active as it
* is non-atomic.
*/
static inline void mapping_set_folio_orders(struct address_space *mapping,
unsigned int min, unsigned int max)
{
if (min == 1)
min = 2;
if (max < min)
max = min;
if (max > MAX_PAGECACHE_ORDER)
max = MAX_PAGECACHE_ORDER;

/*
* XXX: max is ignored as only minimum folio order is supported
* currently.
*/
mapping->flags = (mapping->flags & ~AS_FOLIO_ORDER_MASK) |
(min << AS_FOLIO_ORDER_MIN) |
(MAX_PAGECACHE_ORDER << AS_FOLIO_ORDER_MAX);
}

/**
* mapping_set_large_folios() - Indicate the file supports large folios.
* @mapping: The file.
Expand All @@ -323,7 +376,17 @@ static inline void mapping_set_gfp_mask(struct address_space *m, gfp_t mask)
*/
static inline void mapping_set_large_folios(struct address_space *mapping)
{
__set_bit(AS_LARGE_FOLIO_SUPPORT, &mapping->flags);
mapping_set_folio_orders(mapping, 0, MAX_PAGECACHE_ORDER);
}

static inline unsigned int mapping_max_folio_order(struct address_space *mapping)
{
return (mapping->flags & AS_FOLIO_ORDER_MAX_MASK) >> AS_FOLIO_ORDER_MAX;
}

static inline unsigned int mapping_min_folio_order(struct address_space *mapping)
{
return (mapping->flags & AS_FOLIO_ORDER_MIN_MASK) >> AS_FOLIO_ORDER_MIN;
}

/*
Expand All @@ -332,8 +395,7 @@ static inline void mapping_set_large_folios(struct address_space *mapping)
*/
static inline bool mapping_large_folio_support(struct address_space *mapping)
{
return IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE) &&
test_bit(AS_LARGE_FOLIO_SUPPORT, &mapping->flags);
return mapping_max_folio_order(mapping) > 0;
}

static inline int filemap_nr_thps(struct address_space *mapping)
Expand Down Expand Up @@ -494,19 +556,6 @@ static inline void *detach_page_private(struct page *page)
return folio_detach_private(page_folio(page));
}

/*
* There are some parts of the kernel which assume that PMD entries
* are exactly HPAGE_PMD_ORDER. Those should be fixed, but until then,
* limit the maximum allocation order to PMD size. I'm not aware of any
* assumptions about maximum order if THP are disabled, but 8 seems like
* a good order (that's 1MB if you're using 4kB pages)
*/
#ifdef CONFIG_TRANSPARENT_HUGEPAGE
#define MAX_PAGECACHE_ORDER HPAGE_PMD_ORDER
#else
#define MAX_PAGECACHE_ORDER 8
#endif

#ifdef CONFIG_NUMA
struct folio *filemap_alloc_folio(gfp_t gfp, unsigned int order);
#else
Expand Down

0 comments on commit 27f85d8

Please sign in to comment.