* [PATCH 00/12] [LSF/MM/BPF RFC] shmem/tmpfs: add large folios support
[not found] <CGME20240515055723eucas1p11bf14732f7fac943e688369ff7765f79@eucas1p1.samsung.com>
@ 2024-05-15 5:57 ` Daniel Gomez
[not found] ` <CGME20240515055724eucas1p1c502dbded4dc6ff929c7aff570de80c2@eucas1p1.samsung.com>
` (11 more replies)
0 siblings, 12 replies; 19+ messages in thread
From: Daniel Gomez @ 2024-05-15 5:57 UTC (permalink / raw)
To: hughd, akpm, willy, jack, mcgrof
Cc: linux-mm, linux-xfs, djwong, Pankaj Raghav, dagmcr, yosryahmed,
baolin.wang, ritesh.list, lsf-pc, david, chandan.babu,
linux-kernel, brauner, Daniel Gomez
In preparation for the LSF/MM/BPF 2024 discussion [1], the patches below add
support for large folios in shmem for the write and fallocate paths.
[1] https://lore.kernel.org/all/4ktpayu66noklllpdpspa3vm5gbmb5boxskcj2q6qn7md3pwwt@kvlu64pqwjzl/
test
This version includes per-block uptodate tracking required for lseek when
enabling support for large folios. Initially, this feature was introduced to
address lseek fstests (specifically generic/285 and generic/436) for huge pages.
However, it was suggested that, for THP, the test should be adapted to PAGE_SIZE
and PMD_SIZE. Nevertheless, with arbitrary folio orders we require the lowest
granularity possible. This topic will be part of the discussion in tomorrow's
session.
Fstests expunges results can be found in kdevops' tree:
https://github.com/linux-kdevops/kdevops/tree/main/workflows/fstests/expunges/6.9.0-shmem-large-folios-with-block-tracking/tmpfs
https://github.com/linux-kdevops/kdevops/tree/main/workflows/fstests/expunges/6.8.0-shmem-large-folios-with-block-tracking/tmpfs
Daniel
Daniel Gomez (11):
shmem: add per-block uptodate tracking for large folios
shmem: move folio zero operation to write_begin()
shmem: exit shmem_get_folio_gfp() if block is uptodate
shmem: clear_highpage() if block is not uptodate
shmem: set folio uptodate when reclaim
shmem: check if a block is uptodate before splice into pipe
shmem: clear uptodate blocks after PUNCH_HOLE
shmem: enable per-block uptodate
shmem: add order arg to shmem_alloc_folio()
shmem: add file length arg in shmem_get_folio() path
shmem: add large folio support to the write and fallocate paths
Pankaj Raghav (1):
splice: don't check for uptodate if partially uptodate is impl
fs/splice.c | 17 +-
fs/xfs/scrub/xfile.c | 6 +-
fs/xfs/xfs_buf_mem.c | 3 +-
include/linux/shmem_fs.h | 2 +-
mm/khugepaged.c | 3 +-
mm/shmem.c | 441 ++++++++++++++++++++++++++++++++++-----
mm/userfaultfd.c | 2 +-
7 files changed, 417 insertions(+), 57 deletions(-)
--
2.43.0
^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH 01/12] splice: don't check for uptodate if partially uptodate is impl
[not found] ` <CGME20240515055724eucas1p1c502dbded4dc6ff929c7aff570de80c2@eucas1p1.samsung.com>
@ 2024-05-15 5:57 ` Daniel Gomez
0 siblings, 0 replies; 19+ messages in thread
From: Daniel Gomez @ 2024-05-15 5:57 UTC (permalink / raw)
To: hughd, akpm, willy, jack, mcgrof
Cc: linux-mm, linux-xfs, djwong, Pankaj Raghav, dagmcr, yosryahmed,
baolin.wang, ritesh.list, lsf-pc, david, chandan.babu,
linux-kernel, brauner, Daniel Gomez
From: Pankaj Raghav <p.raghav@samsung.com>
When a large folio is alloced, splice will zero out the whole folio even
if only a small part of it is written, and it updates the uptodate flag
of the folio.
Once the per-block uptodate tracking is implemented for tmpfs,
pipe_buf_confirm() only needs to check the range it needs to splice to
be uptodate and not the whole folio as we don't set uptodate flag for
partial writes.
Signed-off-by: Pankaj Raghav <p.raghav@samsung.com>
Signed-off-by: Daniel Gomez <da.gomez@samsung.com>
---
fs/splice.c | 17 ++++++++++++++---
1 file changed, 14 insertions(+), 3 deletions(-)
diff --git a/fs/splice.c b/fs/splice.c
index 218e24b1ac40..e6ac57795590 100644
--- a/fs/splice.c
+++ b/fs/splice.c
@@ -120,7 +120,9 @@ static int page_cache_pipe_buf_confirm(struct pipe_inode_info *pipe,
struct pipe_buffer *buf)
{
struct folio *folio = page_folio(buf->page);
+ const struct address_space_operations *ops;
int err;
+ off_t off = folio_page_idx(folio, buf->page) * PAGE_SIZE + buf->offset;
if (!folio_test_uptodate(folio)) {
folio_lock(folio);
@@ -134,12 +136,21 @@ static int page_cache_pipe_buf_confirm(struct pipe_inode_info *pipe,
goto error;
}
+ ops = folio->mapping->a_ops;
/*
* Uh oh, read-error from disk.
*/
- if (!folio_test_uptodate(folio)) {
- err = -EIO;
- goto error;
+ if (!ops->is_partially_uptodate) {
+ if (!folio_test_uptodate(folio)) {
+ err = -EIO;
+ goto error;
+ }
+ } else {
+ if (!ops->is_partially_uptodate(folio, off,
+ buf->len)) {
+ err = -EIO;
+ goto error;
+ }
}
/* Folio is ok after all, we are done */
--
2.43.0
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH 02/12] shmem: add per-block uptodate tracking for large folios
[not found] ` <CGME20240515055726eucas1p2a795fc743373571bfc3349f9e1ef3f9e@eucas1p2.samsung.com>
@ 2024-05-15 5:57 ` Daniel Gomez
0 siblings, 0 replies; 19+ messages in thread
From: Daniel Gomez @ 2024-05-15 5:57 UTC (permalink / raw)
To: hughd, akpm, willy, jack, mcgrof
Cc: linux-mm, linux-xfs, djwong, Pankaj Raghav, dagmcr, yosryahmed,
baolin.wang, ritesh.list, lsf-pc, david, chandan.babu,
linux-kernel, brauner, Daniel Gomez
Based on iomap per-block dirty and uptodate state track, add support
for shmem_folio_state struct to track the uptodate state per-block for
large folios.
Signed-off-by: Daniel Gomez <da.gomez@samsung.com>
---
mm/shmem.c | 195 +++++++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 189 insertions(+), 6 deletions(-)
diff --git a/mm/shmem.c b/mm/shmem.c
index 94ab99b6b574..4818f9fbd328 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -131,6 +131,124 @@ struct shmem_options {
#define SHMEM_SEEN_QUOTA 32
};
+/*
+ * Structure allocated for each folio to track per-block uptodate state.
+ *
+ * Like buffered-io iomap_folio_state struct but only for uptodate.
+ */
+struct shmem_folio_state {
+ spinlock_t state_lock;
+ unsigned long state[];
+};
+
+static inline bool sfs_is_fully_uptodate(struct folio *folio)
+{
+ struct inode *inode = folio->mapping->host;
+ struct shmem_folio_state *sfs = folio->private;
+
+ return bitmap_full(sfs->state, i_blocks_per_folio(inode, folio));
+}
+
+static inline bool sfs_is_block_uptodate(struct shmem_folio_state *sfs,
+ unsigned int block)
+{
+ return test_bit(block, sfs->state);
+}
+
+/**
+ * sfs_get_last_block_uptodate - find the index of the last uptodate block
+ * within a specified range
+ * @folio: The folio
+ * @first: The starting block of the range to search
+ * @last: The ending block of the range to search
+ *
+ * Returns the index of the last uptodate block within the specified range. If
+ * a non uptodate block is found at the start, it returns UINT_MAX.
+ */
+static unsigned int sfs_get_last_block_uptodate(struct folio *folio,
+ unsigned int first,
+ unsigned int last)
+{
+ struct inode *inode = folio->mapping->host;
+ struct shmem_folio_state *sfs = folio->private;
+ unsigned int nr_blocks = i_blocks_per_folio(inode, folio);
+ unsigned int aux = find_next_zero_bit(sfs->state, nr_blocks, first);
+
+ /*
+ * Exceed the range of possible last block and return UINT_MAX if a non
+ * uptodate block is found at the beginning of the scan.
+ */
+ if (aux == first)
+ return UINT_MAX;
+
+ return min_t(unsigned int, aux - 1, last);
+}
+
+static void sfs_set_range_uptodate(struct folio *folio,
+ struct shmem_folio_state *sfs, size_t off,
+ size_t len)
+{
+ struct inode *inode = folio->mapping->host;
+ unsigned int first_blk = off >> inode->i_blkbits;
+ unsigned int last_blk = (off + len - 1) >> inode->i_blkbits;
+ unsigned int nr_blks = last_blk - first_blk + 1;
+ unsigned long flags;
+
+ spin_lock_irqsave(&sfs->state_lock, flags);
+ bitmap_set(sfs->state, first_blk, nr_blks);
+ if (sfs_is_fully_uptodate(folio))
+ folio_mark_uptodate(folio);
+ spin_unlock_irqrestore(&sfs->state_lock, flags);
+}
+
+static struct shmem_folio_state *sfs_alloc(struct inode *inode,
+ struct folio *folio)
+{
+ struct shmem_folio_state *sfs = folio->private;
+ unsigned int nr_blocks = i_blocks_per_folio(inode, folio);
+ gfp_t gfp = GFP_KERNEL;
+
+ if (sfs || nr_blocks <= 1)
+ return sfs;
+
+ /*
+ * sfs->state tracks uptodate flag when the block size is smaller
+ * than the folio size.
+ */
+ sfs = kzalloc(struct_size(sfs, state, BITS_TO_LONGS(nr_blocks)), gfp);
+ if (!sfs)
+ return sfs;
+
+ spin_lock_init(&sfs->state_lock);
+ if (folio_test_uptodate(folio))
+ bitmap_set(sfs->state, 0, nr_blocks);
+ folio_attach_private(folio, sfs);
+
+ return sfs;
+}
+
+static void sfs_free(struct folio *folio, bool force)
+{
+ if (!folio_test_private(folio))
+ return;
+
+ if (!force)
+ WARN_ON_ONCE(sfs_is_fully_uptodate(folio) !=
+ folio_test_uptodate(folio));
+
+ kfree(folio_detach_private(folio));
+}
+
+static void shmem_set_range_uptodate(struct folio *folio, size_t off,
+ size_t len)
+{
+ struct shmem_folio_state *sfs = folio->private;
+
+ if (sfs)
+ sfs_set_range_uptodate(folio, sfs, off, len);
+ else
+ folio_mark_uptodate(folio);
+}
#ifdef CONFIG_TMPFS
static unsigned long shmem_default_max_blocks(void)
{
@@ -1487,7 +1605,7 @@ static int shmem_writepage(struct page *page, struct writeback_control *wbc)
}
folio_zero_range(folio, 0, folio_size(folio));
flush_dcache_folio(folio);
- folio_mark_uptodate(folio);
+ shmem_set_range_uptodate(folio, 0, folio_size(folio));
}
swap = folio_alloc_swap(folio);
@@ -1769,13 +1887,16 @@ static int shmem_replace_folio(struct folio **foliop, gfp_t gfp,
if (!new)
return -ENOMEM;
+ if (folio_get_private(old))
+ folio_attach_private(new, folio_detach_private(old));
+
folio_get(new);
folio_copy(new, old);
flush_dcache_folio(new);
__folio_set_locked(new);
__folio_set_swapbacked(new);
- folio_mark_uptodate(new);
+ shmem_set_range_uptodate(new, 0, folio_size(new));
new->swap = entry;
folio_set_swapcache(new);
@@ -2063,6 +2184,12 @@ static int shmem_get_folio_gfp(struct inode *inode, pgoff_t index,
alloced:
alloced = true;
+
+ if (!sfs_alloc(inode, folio) && folio_test_large(folio)) {
+ error = -ENOMEM;
+ goto unlock;
+ }
+
if (folio_test_pmd_mappable(folio) &&
DIV_ROUND_UP(i_size_read(inode), PAGE_SIZE) <
folio_next_index(folio) - 1) {
@@ -2104,7 +2231,7 @@ static int shmem_get_folio_gfp(struct inode *inode, pgoff_t index,
for (i = 0; i < n; i++)
clear_highpage(folio_page(folio, i));
flush_dcache_folio(folio);
- folio_mark_uptodate(folio);
+ shmem_set_range_uptodate(folio, 0, folio_size(folio));
}
/* Perhaps the file has been truncated since we checked */
@@ -2773,8 +2900,8 @@ shmem_write_end(struct file *file, struct address_space *mapping,
folio_zero_segments(folio, 0, from,
from + copied, folio_size(folio));
}
- folio_mark_uptodate(folio);
}
+ shmem_set_range_uptodate(folio, 0, folio_size(folio));
folio_mark_dirty(folio);
folio_unlock(folio);
folio_put(folio);
@@ -2782,6 +2909,59 @@ shmem_write_end(struct file *file, struct address_space *mapping,
return copied;
}
+static void shmem_invalidate_folio(struct folio *folio, size_t offset,
+ size_t len)
+{
+ /*
+ * If we're invalidating the entire folio, clear the dirty state
+ * from it and release it to avoid unnecessary buildup of the LRU.
+ */
+ if (offset == 0 && len == folio_size(folio)) {
+ WARN_ON_ONCE(folio_test_writeback(folio));
+ folio_cancel_dirty(folio);
+ sfs_free(folio, true);
+ }
+}
+
+static bool shmem_release_folio(struct folio *folio, gfp_t gfp_flags)
+{
+ if (folio_test_dirty(folio) && !sfs_is_fully_uptodate(folio))
+ return false;
+
+ sfs_free(folio, false);
+ return true;
+}
+
+/*
+ * shmem_is_partially_uptodate checks whether blocks within a folio are
+ * uptodate or not.
+ *
+ * Returns true if all blocks which correspond to the specified part
+ * of the folio are uptodate.
+ */
+static bool shmem_is_partially_uptodate(struct folio *folio, size_t from,
+ size_t count)
+{
+ struct shmem_folio_state *sfs = folio->private;
+ struct inode *inode = folio->mapping->host;
+ unsigned int first, last;
+
+ if (!sfs)
+ return false;
+
+ /* Caller's range may extend past the end of this folio */
+ count = min(folio_size(folio) - from, count);
+
+ /* First and last blocks in range within folio */
+ first = from >> inode->i_blkbits;
+ last = (from + count - 1) >> inode->i_blkbits;
+
+ if (sfs_get_last_block_uptodate(folio, first, last) != last)
+ return false;
+
+ return true;
+}
+
static ssize_t shmem_file_read_iter(struct kiocb *iocb, struct iov_iter *to)
{
struct file *file = iocb->ki_filp;
@@ -3533,7 +3713,7 @@ static int shmem_symlink(struct mnt_idmap *idmap, struct inode *dir,
goto out_remove_offset;
inode->i_op = &shmem_symlink_inode_operations;
memcpy(folio_address(folio), symname, len);
- folio_mark_uptodate(folio);
+ shmem_set_range_uptodate(folio, 0, folio_size(folio));
folio_mark_dirty(folio);
folio_unlock(folio);
folio_put(folio);
@@ -4523,7 +4703,10 @@ static const struct address_space_operations shmem_aops = {
#ifdef CONFIG_MIGRATION
.migrate_folio = migrate_folio,
#endif
- .error_remove_folio = shmem_error_remove_folio,
+ .error_remove_folio = shmem_error_remove_folio,
+ .invalidate_folio = shmem_invalidate_folio,
+ .release_folio = shmem_release_folio,
+ .is_partially_uptodate = shmem_is_partially_uptodate,
};
static const struct file_operations shmem_file_operations = {
--
2.43.0
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH 03/12] shmem: move folio zero operation to write_begin()
[not found] ` <CGME20240515055727eucas1p2413c65b8b227ac0c6007b4600574abd8@eucas1p2.samsung.com>
@ 2024-05-15 5:57 ` Daniel Gomez
0 siblings, 0 replies; 19+ messages in thread
From: Daniel Gomez @ 2024-05-15 5:57 UTC (permalink / raw)
To: hughd, akpm, willy, jack, mcgrof
Cc: linux-mm, linux-xfs, djwong, Pankaj Raghav, dagmcr, yosryahmed,
baolin.wang, ritesh.list, lsf-pc, david, chandan.babu,
linux-kernel, brauner, Daniel Gomez
Simplify zero out operation by moving it from write_end() to the
write_begin(). If a large folio does not have any block uptodate when we
first get it, zero it out entirely.
Signed-off-by: Daniel Gomez <da.gomez@samsung.com>
---
mm/shmem.c | 27 ++++++++++++++++++++-------
1 file changed, 20 insertions(+), 7 deletions(-)
diff --git a/mm/shmem.c b/mm/shmem.c
index 4818f9fbd328..86ad539b6a0f 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -149,6 +149,14 @@ static inline bool sfs_is_fully_uptodate(struct folio *folio)
return bitmap_full(sfs->state, i_blocks_per_folio(inode, folio));
}
+static inline bool sfs_is_any_uptodate(struct folio *folio)
+{
+ struct inode *inode = folio->mapping->host;
+ struct shmem_folio_state *sfs = folio->private;
+
+ return !bitmap_empty(sfs->state, i_blocks_per_folio(inode, folio));
+}
+
static inline bool sfs_is_block_uptodate(struct shmem_folio_state *sfs,
unsigned int block)
{
@@ -239,6 +247,15 @@ static void sfs_free(struct folio *folio, bool force)
kfree(folio_detach_private(folio));
}
+static inline bool shmem_is_any_uptodate(struct folio *folio)
+{
+ struct shmem_folio_state *sfs = folio->private;
+
+ if (folio_test_large(folio) && sfs)
+ return sfs_is_any_uptodate(folio);
+ return folio_test_uptodate(folio);
+}
+
static void shmem_set_range_uptodate(struct folio *folio, size_t off,
size_t len)
{
@@ -2872,6 +2889,9 @@ shmem_write_begin(struct file *file, struct address_space *mapping,
if (ret)
return ret;
+ if (!shmem_is_any_uptodate(folio))
+ folio_zero_range(folio, 0, folio_size(folio));
+
*pagep = folio_file_page(folio, index);
if (PageHWPoison(*pagep)) {
folio_unlock(folio);
@@ -2894,13 +2914,6 @@ shmem_write_end(struct file *file, struct address_space *mapping,
if (pos + copied > inode->i_size)
i_size_write(inode, pos + copied);
- if (!folio_test_uptodate(folio)) {
- if (copied < folio_size(folio)) {
- size_t from = offset_in_folio(folio, pos);
- folio_zero_segments(folio, 0, from,
- from + copied, folio_size(folio));
- }
- }
shmem_set_range_uptodate(folio, 0, folio_size(folio));
folio_mark_dirty(folio);
folio_unlock(folio);
--
2.43.0
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH 04/12] shmem: exit shmem_get_folio_gfp() if block is uptodate
[not found] ` <CGME20240515055728eucas1p181e0ed81b2663eb0eee6d6134c1c1956@eucas1p1.samsung.com>
@ 2024-05-15 5:57 ` Daniel Gomez
0 siblings, 0 replies; 19+ messages in thread
From: Daniel Gomez @ 2024-05-15 5:57 UTC (permalink / raw)
To: hughd, akpm, willy, jack, mcgrof
Cc: linux-mm, linux-xfs, djwong, Pankaj Raghav, dagmcr, yosryahmed,
baolin.wang, ritesh.list, lsf-pc, david, chandan.babu,
linux-kernel, brauner, Daniel Gomez
When we get a folio from the page cache with filemap_get_entry() and
is uptodate we exit from shmem_get_folio_gfp(). Replicate the same
behaviour if the block is uptodate in the index we are operating on.
Signed-off-by: Daniel Gomez <da.gomez@samsung.com>
---
mm/shmem.c | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)
diff --git a/mm/shmem.c b/mm/shmem.c
index 86ad539b6a0f..69f3b98fdf7c 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -256,6 +256,16 @@ static inline bool shmem_is_any_uptodate(struct folio *folio)
return folio_test_uptodate(folio);
}
+static inline bool shmem_is_block_uptodate(struct folio *folio,
+ unsigned int block)
+{
+ struct shmem_folio_state *sfs = folio->private;
+
+ if (folio_test_large(folio) && sfs)
+ return sfs_is_block_uptodate(sfs, block);
+ return folio_test_uptodate(folio);
+}
+
static void shmem_set_range_uptodate(struct folio *folio, size_t off,
size_t len)
{
@@ -2146,7 +2156,7 @@ static int shmem_get_folio_gfp(struct inode *inode, pgoff_t index,
}
if (sgp == SGP_WRITE)
folio_mark_accessed(folio);
- if (folio_test_uptodate(folio))
+ if (shmem_is_block_uptodate(folio, index - folio_index(folio)))
goto out;
/* fallocated folio */
if (sgp != SGP_READ)
--
2.43.0
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH 05/12] shmem: clear_highpage() if block is not uptodate
[not found] ` <CGME20240515055729eucas1p14e953424ad39bbb923c64163b1bbd4b3@eucas1p1.samsung.com>
@ 2024-05-15 5:57 ` Daniel Gomez
0 siblings, 0 replies; 19+ messages in thread
From: Daniel Gomez @ 2024-05-15 5:57 UTC (permalink / raw)
To: hughd, akpm, willy, jack, mcgrof
Cc: linux-mm, linux-xfs, djwong, Pankaj Raghav, dagmcr, yosryahmed,
baolin.wang, ritesh.list, lsf-pc, david, chandan.babu,
linux-kernel, brauner, Daniel Gomez
clear_highpage() is called for all the subpages (blocks) in a large
folio when the folio is not uptodate. Do clear the subpages only when
they are not uptodate.
Signed-off-by: Daniel Gomez <da.gomez@samsung.com>
---
mm/shmem.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/mm/shmem.c b/mm/shmem.c
index 69f3b98fdf7c..04992010225f 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -2256,7 +2256,8 @@ static int shmem_get_folio_gfp(struct inode *inode, pgoff_t index,
long i, n = folio_nr_pages(folio);
for (i = 0; i < n; i++)
- clear_highpage(folio_page(folio, i));
+ if (!shmem_is_block_uptodate(folio, i))
+ clear_highpage(folio_page(folio, i));
flush_dcache_folio(folio);
shmem_set_range_uptodate(folio, 0, folio_size(folio));
}
--
2.43.0
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH 06/12] shmem: set folio uptodate when reclaim
[not found] ` <CGME20240515055731eucas1p12cbbba88e24a011ef5871f90ff25ae73@eucas1p1.samsung.com>
@ 2024-05-15 5:57 ` Daniel Gomez
0 siblings, 0 replies; 19+ messages in thread
From: Daniel Gomez @ 2024-05-15 5:57 UTC (permalink / raw)
To: hughd, akpm, willy, jack, mcgrof
Cc: linux-mm, linux-xfs, djwong, Pankaj Raghav, dagmcr, yosryahmed,
baolin.wang, ritesh.list, lsf-pc, david, chandan.babu,
linux-kernel, brauner, Daniel Gomez
When reclaiming some space by splitting a large folio through
shmem_unused_huge_shrink(), a large folio is split regardless of its
uptodate status. Mark all the blocks as uptodate in the reclaim path so
split_folio() can release the folio private struct (shmem_folio_state).
Signed-off-by: Daniel Gomez <da.gomez@samsung.com>
---
mm/shmem.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/mm/shmem.c b/mm/shmem.c
index 04992010225f..68fe769d91b1 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -842,6 +842,7 @@ static unsigned long shmem_unused_huge_shrink(struct shmem_sb_info *sbinfo,
goto move_back;
}
+ shmem_set_range_uptodate(folio, 0, folio_size(folio));
ret = split_folio(folio);
folio_unlock(folio);
folio_put(folio);
--
2.43.0
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH 07/12] shmem: check if a block is uptodate before splice into pipe
[not found] ` <CGME20240515055732eucas1p2302bbca4d60e2e811a5c59e34f83628d@eucas1p2.samsung.com>
@ 2024-05-15 5:57 ` Daniel Gomez
2024-05-16 13:19 ` kernel test robot
0 siblings, 1 reply; 19+ messages in thread
From: Daniel Gomez @ 2024-05-15 5:57 UTC (permalink / raw)
To: hughd, akpm, willy, jack, mcgrof
Cc: linux-mm, linux-xfs, djwong, Pankaj Raghav, dagmcr, yosryahmed,
baolin.wang, ritesh.list, lsf-pc, david, chandan.babu,
linux-kernel, brauner, Daniel Gomez
The splice_read() path assumes folios are always uptodate. Make sure
all blocks in the given range are uptodate or else, splice zeropage into
the pipe. Maximize the number of blocks that can be spliced into pipe at
once by increasing the 'part' to the latest uptodate block found.
Signed-off-by: Daniel Gomez <da.gomez@samsung.com>
---
mm/shmem.c | 24 +++++++++++++++++++++++-
1 file changed, 23 insertions(+), 1 deletion(-)
diff --git a/mm/shmem.c b/mm/shmem.c
index 68fe769d91b1..e06cb6438ef8 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -3223,8 +3223,30 @@ static ssize_t shmem_file_splice_read(struct file *in, loff_t *ppos,
if (unlikely(*ppos >= isize))
break;
part = min_t(loff_t, isize - *ppos, len);
+ if (folio && folio_test_large(folio) &&
+ folio_test_private(folio)) {
+ unsigned long from = offset_in_folio(folio, *ppos);
+ unsigned int bfirst = from >> inode->i_blkbits;
+ unsigned int blast, blast_upd;
+
+ len = min(folio_size(folio) - from, len);
+ blast = (from + len - 1) >> inode->i_blkbits;
+
+ blast_upd = sfs_get_last_block_uptodate(folio, bfirst,
+ blast);
+ if (blast_upd <= blast) {
+ unsigned int bsize = 1 << inode->i_blkbits;
+ unsigned int blks = blast_upd - bfirst + 1;
+ unsigned int bbytes = blks << inode->i_blkbits;
+ unsigned int boff = (*ppos % bsize);
+
+ part = min_t(loff_t, bbytes - boff, len);
+ }
+ }
- if (folio) {
+ if (folio && shmem_is_block_uptodate(
+ folio, offset_in_folio(folio, *ppos) >>
+ inode->i_blkbits)) {
/*
* If users can be writing to this page using arbitrary
* virtual addresses, take care about potential aliasing
--
2.43.0
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH 08/12] shmem: clear uptodate blocks after PUNCH_HOLE
[not found] ` <CGME20240515055733eucas1p2804d2fb5f5bf7d6adb460054f6e9f4d8@eucas1p2.samsung.com>
@ 2024-05-15 5:57 ` Daniel Gomez
0 siblings, 0 replies; 19+ messages in thread
From: Daniel Gomez @ 2024-05-15 5:57 UTC (permalink / raw)
To: hughd, akpm, willy, jack, mcgrof
Cc: linux-mm, linux-xfs, djwong, Pankaj Raghav, dagmcr, yosryahmed,
baolin.wang, ritesh.list, lsf-pc, david, chandan.babu,
linux-kernel, brauner, Daniel Gomez
In the fallocate path with PUNCH_HOLE mode flag enabled, clear the
uptodate flag for those blocks covered by the punch. Skip all partial
blocks as they may still contain data.
Signed-off-by: Daniel Gomez <da.gomez@samsung.com>
---
mm/shmem.c | 78 +++++++++++++++++++++++++++++++++++++++++++++++++-----
1 file changed, 72 insertions(+), 6 deletions(-)
diff --git a/mm/shmem.c b/mm/shmem.c
index e06cb6438ef8..d5e6c8eba983 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -209,6 +209,28 @@ static void sfs_set_range_uptodate(struct folio *folio,
spin_unlock_irqrestore(&sfs->state_lock, flags);
}
+static void sfs_clear_range_uptodate(struct folio *folio,
+ struct shmem_folio_state *sfs, size_t off,
+ size_t len)
+{
+ struct inode *inode = folio->mapping->host;
+ unsigned int first_blk, last_blk;
+ unsigned long flags;
+
+ first_blk = DIV_ROUND_UP_ULL(off, 1 << inode->i_blkbits);
+ last_blk = DIV_ROUND_DOWN_ULL(off + len, 1 << inode->i_blkbits) - 1;
+ if (last_blk == UINT_MAX)
+ return;
+
+ if (first_blk > last_blk)
+ return;
+
+ spin_lock_irqsave(&sfs->state_lock, flags);
+ bitmap_clear(sfs->state, first_blk, last_blk - first_blk + 1);
+ folio_clear_uptodate(folio);
+ spin_unlock_irqrestore(&sfs->state_lock, flags);
+}
+
static struct shmem_folio_state *sfs_alloc(struct inode *inode,
struct folio *folio)
{
@@ -276,6 +298,19 @@ static void shmem_set_range_uptodate(struct folio *folio, size_t off,
else
folio_mark_uptodate(folio);
}
+
+static void shmem_clear_range_uptodate(struct folio *folio, size_t off,
+ size_t len)
+{
+ struct shmem_folio_state *sfs = folio->private;
+
+ if (sfs)
+ sfs_clear_range_uptodate(folio, sfs, off, len);
+ else
+ folio_clear_uptodate(folio);
+
+}
+
#ifdef CONFIG_TMPFS
static unsigned long shmem_default_max_blocks(void)
{
@@ -1103,12 +1138,33 @@ static struct folio *shmem_get_partial_folio(struct inode *inode, pgoff_t index)
return folio;
}
+static void shmem_clear(struct folio *folio, loff_t start, loff_t end, int mode)
+{
+ loff_t pos = folio_pos(folio);
+ unsigned int offset, length;
+
+ if (!(mode & FALLOC_FL_PUNCH_HOLE) || !(folio_test_large(folio)))
+ return;
+
+ if (pos < start)
+ offset = start - pos;
+ else
+ offset = 0;
+ length = folio_size(folio);
+ if (pos + length <= (u64)end)
+ length = length - offset;
+ else
+ length = end + 1 - pos - offset;
+
+ shmem_clear_range_uptodate(folio, offset, length);
+}
+
/*
* Remove range of pages and swap entries from page cache, and free them.
* If !unfalloc, truncate or punch hole; if unfalloc, undo failed fallocate.
*/
static void shmem_undo_range(struct inode *inode, loff_t lstart, loff_t lend,
- bool unfalloc)
+ bool unfalloc, int mode)
{
struct address_space *mapping = inode->i_mapping;
struct shmem_inode_info *info = SHMEM_I(inode);
@@ -1166,6 +1222,7 @@ static void shmem_undo_range(struct inode *inode, loff_t lstart, loff_t lend,
if (folio) {
same_folio = lend < folio_pos(folio) + folio_size(folio);
folio_mark_dirty(folio);
+ shmem_clear(folio, lstart, lend, mode);
if (!truncate_inode_partial_folio(folio, lstart, lend)) {
start = folio_next_index(folio);
if (same_folio)
@@ -1255,9 +1312,17 @@ static void shmem_undo_range(struct inode *inode, loff_t lstart, loff_t lend,
shmem_recalc_inode(inode, 0, -nr_swaps_freed);
}
+static void shmem_truncate_range_mode(struct inode *inode, loff_t lstart,
+ loff_t lend, int mode)
+{
+ shmem_undo_range(inode, lstart, lend, false, mode);
+ inode_set_mtime_to_ts(inode, inode_set_ctime_current(inode));
+ inode_inc_iversion(inode);
+}
+
void shmem_truncate_range(struct inode *inode, loff_t lstart, loff_t lend)
{
- shmem_undo_range(inode, lstart, lend, false);
+ shmem_undo_range(inode, lstart, lend, false, 0);
inode_set_mtime_to_ts(inode, inode_set_ctime_current(inode));
inode_inc_iversion(inode);
}
@@ -3342,7 +3407,7 @@ static long shmem_fallocate(struct file *file, int mode, loff_t offset,
if ((u64)unmap_end > (u64)unmap_start)
unmap_mapping_range(mapping, unmap_start,
1 + unmap_end - unmap_start, 0);
- shmem_truncate_range(inode, offset, offset + len - 1);
+ shmem_truncate_range_mode(inode, offset, offset + len - 1, mode);
/* No need to unmap again: hole-punching leaves COWed pages */
spin_lock(&inode->i_lock);
@@ -3408,9 +3473,10 @@ static long shmem_fallocate(struct file *file, int mode, loff_t offset,
info->fallocend = undo_fallocend;
/* Remove the !uptodate folios we added */
if (index > start) {
- shmem_undo_range(inode,
- (loff_t)start << PAGE_SHIFT,
- ((loff_t)index << PAGE_SHIFT) - 1, true);
+ shmem_undo_range(
+ inode, (loff_t)start << PAGE_SHIFT,
+ ((loff_t)index << PAGE_SHIFT) - 1, true,
+ 0);
}
goto undone;
}
--
2.43.0
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH 09/12] shmem: enable per-block uptodate
[not found] ` <CGME20240515055735eucas1p2a967b4eebc8e059588cd62139f006b0d@eucas1p2.samsung.com>
@ 2024-05-15 5:57 ` Daniel Gomez
0 siblings, 0 replies; 19+ messages in thread
From: Daniel Gomez @ 2024-05-15 5:57 UTC (permalink / raw)
To: hughd, akpm, willy, jack, mcgrof
Cc: linux-mm, linux-xfs, djwong, Pankaj Raghav, dagmcr, yosryahmed,
baolin.wang, ritesh.list, lsf-pc, david, chandan.babu,
linux-kernel, brauner, Daniel Gomez
In the write_end() function, mark only the blocks that are being written
as uptodate.
Signed-off-by: Daniel Gomez <da.gomez@samsung.com>
---
mm/shmem.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/mm/shmem.c b/mm/shmem.c
index d5e6c8eba983..7a6ad678e2ff 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -2991,7 +2991,7 @@ shmem_write_end(struct file *file, struct address_space *mapping,
if (pos + copied > inode->i_size)
i_size_write(inode, pos + copied);
- shmem_set_range_uptodate(folio, 0, folio_size(folio));
+ shmem_set_range_uptodate(folio, offset_in_folio(folio, pos), len);
folio_mark_dirty(folio);
folio_unlock(folio);
folio_put(folio);
--
2.43.0
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH 10/12] shmem: add order arg to shmem_alloc_folio()
[not found] ` <CGME20240515055736eucas1p1bfa9549398e766532d143ba9314bee18@eucas1p1.samsung.com>
@ 2024-05-15 5:57 ` Daniel Gomez
0 siblings, 0 replies; 19+ messages in thread
From: Daniel Gomez @ 2024-05-15 5:57 UTC (permalink / raw)
To: hughd, akpm, willy, jack, mcgrof
Cc: linux-mm, linux-xfs, djwong, Pankaj Raghav, dagmcr, yosryahmed,
baolin.wang, ritesh.list, lsf-pc, david, chandan.babu,
linux-kernel, brauner, Daniel Gomez
Add folio order argument to the shmem_alloc_folio(). Return will make
use of the new page_rmappable_folio() where order-0 and high order
folios are both supported.
As the order requested may not match the order returned when allocating
high order folios, make sure pages are calculated after getting the
folio.
Signed-off-by: Daniel Gomez <da.gomez@samsung.com>
---
mm/shmem.c | 21 +++++++++++----------
1 file changed, 11 insertions(+), 10 deletions(-)
diff --git a/mm/shmem.c b/mm/shmem.c
index 7a6ad678e2ff..d531018ffece 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -1828,18 +1828,18 @@ static struct folio *shmem_alloc_hugefolio(gfp_t gfp,
return page_rmappable_folio(page);
}
-static struct folio *shmem_alloc_folio(gfp_t gfp,
- struct shmem_inode_info *info, pgoff_t index)
+static struct folio *shmem_alloc_folio(gfp_t gfp, struct shmem_inode_info *info,
+ pgoff_t index, unsigned int order)
{
struct mempolicy *mpol;
pgoff_t ilx;
struct page *page;
- mpol = shmem_get_pgoff_policy(info, index, 0, &ilx);
- page = alloc_pages_mpol(gfp, 0, mpol, ilx, numa_node_id());
+ mpol = shmem_get_pgoff_policy(info, index, order, &ilx);
+ page = alloc_pages_mpol(gfp, order, mpol, ilx, numa_node_id());
mpol_cond_put(mpol);
- return (struct folio *)page;
+ return page_rmappable_folio(page);
}
static struct folio *shmem_alloc_and_add_folio(gfp_t gfp,
@@ -1848,6 +1848,7 @@ static struct folio *shmem_alloc_and_add_folio(gfp_t gfp,
{
struct address_space *mapping = inode->i_mapping;
struct shmem_inode_info *info = SHMEM_I(inode);
+ unsigned int order = 0;
struct folio *folio;
long pages;
int error;
@@ -1856,7 +1857,6 @@ static struct folio *shmem_alloc_and_add_folio(gfp_t gfp,
huge = false;
if (huge) {
- pages = HPAGE_PMD_NR;
index = round_down(index, HPAGE_PMD_NR);
/*
@@ -1875,12 +1875,13 @@ static struct folio *shmem_alloc_and_add_folio(gfp_t gfp,
if (!folio)
count_vm_event(THP_FILE_FALLBACK);
} else {
- pages = 1;
- folio = shmem_alloc_folio(gfp, info, index);
+ folio = shmem_alloc_folio(gfp, info, index, order);
}
if (!folio)
return ERR_PTR(-ENOMEM);
+ pages = folio_nr_pages(folio);
+
__folio_set_locked(folio);
__folio_set_swapbacked(folio);
@@ -1976,7 +1977,7 @@ static int shmem_replace_folio(struct folio **foliop, gfp_t gfp,
*/
gfp &= ~GFP_CONSTRAINT_MASK;
VM_BUG_ON_FOLIO(folio_test_large(old), old);
- new = shmem_alloc_folio(gfp, info, index);
+ new = shmem_alloc_folio(gfp, info, index, folio_order(old));
if (!new)
return -ENOMEM;
@@ -2855,7 +2856,7 @@ int shmem_mfill_atomic_pte(pmd_t *dst_pmd,
if (!*foliop) {
ret = -ENOMEM;
- folio = shmem_alloc_folio(gfp, info, pgoff);
+ folio = shmem_alloc_folio(gfp, info, pgoff, 0);
if (!folio)
goto out_unacct_blocks;
--
2.43.0
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH 11/12] shmem: add file length arg in shmem_get_folio() path
[not found] ` <CGME20240515055738eucas1p15335a32c790b731aa5857193bbddf92d@eucas1p1.samsung.com>
@ 2024-05-15 5:57 ` Daniel Gomez
2024-05-15 17:47 ` kernel test robot
2024-05-17 16:17 ` Darrick J. Wong
0 siblings, 2 replies; 19+ messages in thread
From: Daniel Gomez @ 2024-05-15 5:57 UTC (permalink / raw)
To: hughd, akpm, willy, jack, mcgrof
Cc: linux-mm, linux-xfs, djwong, Pankaj Raghav, dagmcr, yosryahmed,
baolin.wang, ritesh.list, lsf-pc, david, chandan.babu,
linux-kernel, brauner, Daniel Gomez
In preparation for large folio in the write and fallocate paths, add
file length argument in shmem_get_folio() path to be able to calculate
the folio order based on the file size. Use of order-0 (PAGE_SIZE) for
read, page cache read, and vm fault.
This enables high order folios in the write and fallocate path once the
folio order is calculated based on the length.
Signed-off-by: Daniel Gomez <da.gomez@samsung.com>
---
fs/xfs/scrub/xfile.c | 6 +++---
fs/xfs/xfs_buf_mem.c | 3 ++-
include/linux/shmem_fs.h | 2 +-
mm/khugepaged.c | 3 ++-
mm/shmem.c | 35 ++++++++++++++++++++---------------
mm/userfaultfd.c | 2 +-
6 files changed, 29 insertions(+), 22 deletions(-)
diff --git a/fs/xfs/scrub/xfile.c b/fs/xfs/scrub/xfile.c
index 8cdd863db585..4905f5e4cb5d 100644
--- a/fs/xfs/scrub/xfile.c
+++ b/fs/xfs/scrub/xfile.c
@@ -127,7 +127,7 @@ xfile_load(
unsigned int offset;
if (shmem_get_folio(inode, pos >> PAGE_SHIFT, &folio,
- SGP_READ) < 0)
+ SGP_READ, PAGE_SIZE) < 0)
break;
if (!folio) {
/*
@@ -197,7 +197,7 @@ xfile_store(
unsigned int offset;
if (shmem_get_folio(inode, pos >> PAGE_SHIFT, &folio,
- SGP_CACHE) < 0)
+ SGP_CACHE, PAGE_SIZE) < 0)
break;
if (filemap_check_wb_err(inode->i_mapping, 0)) {
folio_unlock(folio);
@@ -268,7 +268,7 @@ xfile_get_folio(
pflags = memalloc_nofs_save();
error = shmem_get_folio(inode, pos >> PAGE_SHIFT, &folio,
- (flags & XFILE_ALLOC) ? SGP_CACHE : SGP_READ);
+ (flags & XFILE_ALLOC) ? SGP_CACHE : SGP_READ, PAGE_SIZE);
memalloc_nofs_restore(pflags);
if (error)
return ERR_PTR(error);
diff --git a/fs/xfs/xfs_buf_mem.c b/fs/xfs/xfs_buf_mem.c
index 9bb2d24de709..784c81d35a1f 100644
--- a/fs/xfs/xfs_buf_mem.c
+++ b/fs/xfs/xfs_buf_mem.c
@@ -149,7 +149,8 @@ xmbuf_map_page(
return -ENOMEM;
}
- error = shmem_get_folio(inode, pos >> PAGE_SHIFT, &folio, SGP_CACHE);
+ error = shmem_get_folio(inode, pos >> PAGE_SHIFT, &folio, SGP_CACHE,
+ PAGE_SIZE);
if (error)
return error;
diff --git a/include/linux/shmem_fs.h b/include/linux/shmem_fs.h
index 3fb18f7eb73e..bc59b4a00228 100644
--- a/include/linux/shmem_fs.h
+++ b/include/linux/shmem_fs.h
@@ -142,7 +142,7 @@ enum sgp_type {
};
int shmem_get_folio(struct inode *inode, pgoff_t index, struct folio **foliop,
- enum sgp_type sgp);
+ enum sgp_type sgp, size_t len);
struct folio *shmem_read_folio_gfp(struct address_space *mapping,
pgoff_t index, gfp_t gfp);
diff --git a/mm/khugepaged.c b/mm/khugepaged.c
index 38830174608f..947770ded68c 100644
--- a/mm/khugepaged.c
+++ b/mm/khugepaged.c
@@ -1863,7 +1863,8 @@ static int collapse_file(struct mm_struct *mm, unsigned long addr,
xas_unlock_irq(&xas);
/* swap in or instantiate fallocated page */
if (shmem_get_folio(mapping->host, index,
- &folio, SGP_NOALLOC)) {
+ &folio, SGP_NOALLOC,
+ PAGE_SIZE)) {
result = SCAN_FAIL;
goto xa_unlocked;
}
diff --git a/mm/shmem.c b/mm/shmem.c
index d531018ffece..fcd2c9befe19 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -1134,7 +1134,7 @@ static struct folio *shmem_get_partial_folio(struct inode *inode, pgoff_t index)
* (although in some cases this is just a waste of time).
*/
folio = NULL;
- shmem_get_folio(inode, index, &folio, SGP_READ);
+ shmem_get_folio(inode, index, &folio, SGP_READ, PAGE_SIZE);
return folio;
}
@@ -1844,7 +1844,7 @@ static struct folio *shmem_alloc_folio(gfp_t gfp, struct shmem_inode_info *info,
static struct folio *shmem_alloc_and_add_folio(gfp_t gfp,
struct inode *inode, pgoff_t index,
- struct mm_struct *fault_mm, bool huge)
+ struct mm_struct *fault_mm, bool huge, size_t len)
{
struct address_space *mapping = inode->i_mapping;
struct shmem_inode_info *info = SHMEM_I(inode);
@@ -2173,7 +2173,7 @@ static int shmem_swapin_folio(struct inode *inode, pgoff_t index,
*/
static int shmem_get_folio_gfp(struct inode *inode, pgoff_t index,
struct folio **foliop, enum sgp_type sgp, gfp_t gfp,
- struct vm_fault *vmf, vm_fault_t *fault_type)
+ struct vm_fault *vmf, vm_fault_t *fault_type, size_t len)
{
struct vm_area_struct *vma = vmf ? vmf->vma : NULL;
struct mm_struct *fault_mm;
@@ -2258,7 +2258,7 @@ static int shmem_get_folio_gfp(struct inode *inode, pgoff_t index,
huge_gfp = vma_thp_gfp_mask(vma);
huge_gfp = limit_gfp_mask(huge_gfp, gfp);
folio = shmem_alloc_and_add_folio(huge_gfp,
- inode, index, fault_mm, true);
+ inode, index, fault_mm, true, len);
if (!IS_ERR(folio)) {
count_vm_event(THP_FILE_ALLOC);
goto alloced;
@@ -2267,7 +2267,8 @@ static int shmem_get_folio_gfp(struct inode *inode, pgoff_t index,
goto repeat;
}
- folio = shmem_alloc_and_add_folio(gfp, inode, index, fault_mm, false);
+ folio = shmem_alloc_and_add_folio(gfp, inode, index, fault_mm, false,
+ len);
if (IS_ERR(folio)) {
error = PTR_ERR(folio);
if (error == -EEXIST)
@@ -2377,10 +2378,10 @@ static int shmem_get_folio_gfp(struct inode *inode, pgoff_t index,
* Return: 0 if successful, else a negative error code.
*/
int shmem_get_folio(struct inode *inode, pgoff_t index, struct folio **foliop,
- enum sgp_type sgp)
+ enum sgp_type sgp, size_t len)
{
return shmem_get_folio_gfp(inode, index, foliop, sgp,
- mapping_gfp_mask(inode->i_mapping), NULL, NULL);
+ mapping_gfp_mask(inode->i_mapping), NULL, NULL, len);
}
EXPORT_SYMBOL_GPL(shmem_get_folio);
@@ -2475,7 +2476,7 @@ static vm_fault_t shmem_fault(struct vm_fault *vmf)
WARN_ON_ONCE(vmf->page != NULL);
err = shmem_get_folio_gfp(inode, vmf->pgoff, &folio, SGP_CACHE,
- gfp, vmf, &ret);
+ gfp, vmf, &ret, PAGE_SIZE);
if (err)
return vmf_error(err);
if (folio) {
@@ -2954,6 +2955,9 @@ shmem_write_begin(struct file *file, struct address_space *mapping,
struct folio *folio;
int ret = 0;
+ if (!mapping_large_folio_support(mapping))
+ len = min_t(size_t, len, PAGE_SIZE - offset_in_page(pos));
+
/* i_rwsem is held by caller */
if (unlikely(info->seals & (F_SEAL_GROW |
F_SEAL_WRITE | F_SEAL_FUTURE_WRITE))) {
@@ -2963,7 +2967,7 @@ shmem_write_begin(struct file *file, struct address_space *mapping,
return -EPERM;
}
- ret = shmem_get_folio(inode, index, &folio, SGP_WRITE);
+ ret = shmem_get_folio(inode, index, &folio, SGP_WRITE, len);
if (ret)
return ret;
@@ -3083,7 +3087,7 @@ static ssize_t shmem_file_read_iter(struct kiocb *iocb, struct iov_iter *to)
break;
}
- error = shmem_get_folio(inode, index, &folio, SGP_READ);
+ error = shmem_get_folio(inode, index, &folio, SGP_READ, PAGE_SIZE);
if (error) {
if (error == -EINVAL)
error = 0;
@@ -3260,7 +3264,7 @@ static ssize_t shmem_file_splice_read(struct file *in, loff_t *ppos,
break;
error = shmem_get_folio(inode, *ppos / PAGE_SIZE, &folio,
- SGP_READ);
+ SGP_READ, PAGE_SIZE);
if (error) {
if (error == -EINVAL)
error = 0;
@@ -3469,7 +3473,8 @@ static long shmem_fallocate(struct file *file, int mode, loff_t offset,
error = -ENOMEM;
else
error = shmem_get_folio(inode, index, &folio,
- SGP_FALLOC);
+ SGP_FALLOC,
+ (end - index) << PAGE_SHIFT);
if (error) {
info->fallocend = undo_fallocend;
/* Remove the !uptodate folios we added */
@@ -3822,7 +3827,7 @@ static int shmem_symlink(struct mnt_idmap *idmap, struct inode *dir,
} else {
inode_nohighmem(inode);
inode->i_mapping->a_ops = &shmem_aops;
- error = shmem_get_folio(inode, 0, &folio, SGP_WRITE);
+ error = shmem_get_folio(inode, 0, &folio, SGP_WRITE, PAGE_SIZE);
if (error)
goto out_remove_offset;
inode->i_op = &shmem_symlink_inode_operations;
@@ -3868,7 +3873,7 @@ static const char *shmem_get_link(struct dentry *dentry, struct inode *inode,
return ERR_PTR(-ECHILD);
}
} else {
- error = shmem_get_folio(inode, 0, &folio, SGP_READ);
+ error = shmem_get_folio(inode, 0, &folio, SGP_READ, PAGE_SIZE);
if (error)
return ERR_PTR(error);
if (!folio)
@@ -5255,7 +5260,7 @@ struct folio *shmem_read_folio_gfp(struct address_space *mapping,
int error;
error = shmem_get_folio_gfp(inode, index, &folio, SGP_CACHE,
- gfp, NULL, NULL);
+ gfp, NULL, NULL, PAGE_SIZE);
if (error)
return ERR_PTR(error);
diff --git a/mm/userfaultfd.c b/mm/userfaultfd.c
index 3c3539c573e7..540a0c2d4325 100644
--- a/mm/userfaultfd.c
+++ b/mm/userfaultfd.c
@@ -359,7 +359,7 @@ static int mfill_atomic_pte_continue(pmd_t *dst_pmd,
struct page *page;
int ret;
- ret = shmem_get_folio(inode, pgoff, &folio, SGP_NOALLOC);
+ ret = shmem_get_folio(inode, pgoff, &folio, SGP_NOALLOC, PAGE_SIZE);
/* Our caller expects us to return -EFAULT if we failed to find folio */
if (ret == -ENOENT)
ret = -EFAULT;
--
2.43.0
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH 12/12] shmem: add large folio support to the write and fallocate paths
[not found] ` <CGME20240515055740eucas1p1bf112e73a7009a0f9b2bbf09c989a51b@eucas1p1.samsung.com>
@ 2024-05-15 5:57 ` Daniel Gomez
2024-05-15 18:59 ` kernel test robot
0 siblings, 1 reply; 19+ messages in thread
From: Daniel Gomez @ 2024-05-15 5:57 UTC (permalink / raw)
To: hughd, akpm, willy, jack, mcgrof
Cc: linux-mm, linux-xfs, djwong, Pankaj Raghav, dagmcr, yosryahmed,
baolin.wang, ritesh.list, lsf-pc, david, chandan.babu,
linux-kernel, brauner, Daniel Gomez
Add large folio support for shmem write and fallocate paths matching the
same high order preference mechanism used in the iomap buffered IO path
as used in __filemap_get_folio().
Add shmem_mapping_size_order() to get a hint for the order of the folio
based on the file size which takes care of the mapping requirements.
Swap does not support high order folios for now, so make it order-0 in
case swap is enabled.
Skip high order folio allocation loop when reclaim path returns with no
space left (ENOSPC).
Add __GFP_COMP flag for high order folios allocation path to fix a
memory leak.
Signed-off-by: Daniel Gomez <da.gomez@samsung.com>
---
mm/shmem.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 47 insertions(+), 2 deletions(-)
diff --git a/mm/shmem.c b/mm/shmem.c
index fcd2c9befe19..9308a334a940 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -1836,23 +1836,63 @@ static struct folio *shmem_alloc_folio(gfp_t gfp, struct shmem_inode_info *info,
struct page *page;
mpol = shmem_get_pgoff_policy(info, index, order, &ilx);
- page = alloc_pages_mpol(gfp, order, mpol, ilx, numa_node_id());
+ page = alloc_pages_mpol(gfp | __GFP_COMP, order, mpol, ilx,
+ numa_node_id());
mpol_cond_put(mpol);
return page_rmappable_folio(page);
}
+/**
+ * shmem_mapping_size_order - Get maximum folio order for the given file size.
+ * @mapping: Target address_space.
+ * @index: The page index.
+ * @size: The suggested size of the folio to create.
+ *
+ * This returns a high order for folios (when supported) based on the file size
+ * which the mapping currently allows at the given index. The index is relevant
+ * due to alignment considerations the mapping might have. The returned order
+ * may be less than the size passed.
+ *
+ * Like __filemap_get_folio order calculation.
+ *
+ * Return: The order.
+ */
+static inline unsigned int
+shmem_mapping_size_order(struct address_space *mapping, pgoff_t index,
+ size_t size, struct shmem_sb_info *sbinfo)
+{
+ unsigned int order = ilog2(size);
+
+ if ((order <= PAGE_SHIFT) ||
+ (!mapping_large_folio_support(mapping) || !sbinfo->noswap))
+ return 0;
+
+ order -= PAGE_SHIFT;
+
+ /* If we're not aligned, allocate a smaller folio */
+ if (index & ((1UL << order) - 1))
+ order = __ffs(index);
+
+ order = min_t(size_t, order, MAX_PAGECACHE_ORDER);
+
+ /* Order-1 not supported due to THP dependency */
+ return (order == 1) ? 0 : order;
+}
+
static struct folio *shmem_alloc_and_add_folio(gfp_t gfp,
struct inode *inode, pgoff_t index,
struct mm_struct *fault_mm, bool huge, size_t len)
{
struct address_space *mapping = inode->i_mapping;
struct shmem_inode_info *info = SHMEM_I(inode);
- unsigned int order = 0;
+ unsigned int order = shmem_mapping_size_order(mapping, index, len,
+ SHMEM_SB(inode->i_sb));
struct folio *folio;
long pages;
int error;
+neworder:
if (!IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE))
huge = false;
@@ -1937,6 +1977,11 @@ static struct folio *shmem_alloc_and_add_folio(gfp_t gfp,
unlock:
folio_unlock(folio);
folio_put(folio);
+ if ((error != -ENOSPC) && (order > 0)) {
+ if (--order == 1)
+ order = 0;
+ goto neworder;
+ }
return ERR_PTR(error);
}
--
2.43.0
^ permalink raw reply related [flat|nested] 19+ messages in thread
* Re: [PATCH 11/12] shmem: add file length arg in shmem_get_folio() path
2024-05-15 5:57 ` [PATCH 11/12] shmem: add file length arg in shmem_get_folio() path Daniel Gomez
@ 2024-05-15 17:47 ` kernel test robot
2024-05-17 16:17 ` Darrick J. Wong
1 sibling, 0 replies; 19+ messages in thread
From: kernel test robot @ 2024-05-15 17:47 UTC (permalink / raw)
To: Daniel Gomez, hughd, akpm, willy, jack, mcgrof
Cc: oe-kbuild-all, linux-mm, linux-xfs, djwong, Pankaj Raghav,
dagmcr, yosryahmed, baolin.wang, ritesh.list, lsf-pc, david,
chandan.babu, linux-kernel, brauner, Daniel Gomez
Hi Daniel,
kernel test robot noticed the following build warnings:
[auto build test WARNING on akpm-mm/mm-everything]
[also build test WARNING on xfs-linux/for-next brauner-vfs/vfs.all linus/master v6.9 next-20240515]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Daniel-Gomez/splice-don-t-check-for-uptodate-if-partially-uptodate-is-impl/20240515-135925
base: https://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm.git mm-everything
patch link: https://lore.kernel.org/r/20240515055719.32577-12-da.gomez%40samsung.com
patch subject: [PATCH 11/12] shmem: add file length arg in shmem_get_folio() path
config: openrisc-defconfig (https://download.01.org/0day-ci/archive/20240516/202405160144.a9ad9CX5-lkp@intel.com/config)
compiler: or1k-linux-gcc (GCC) 13.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20240516/202405160144.a9ad9CX5-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202405160144.a9ad9CX5-lkp@intel.com/
All warnings (new ones prefixed by >>):
>> mm/shmem.c:2382: warning: Function parameter or struct member 'len' not described in 'shmem_get_folio'
vim +2382 mm/shmem.c
^1da177e4c3f41 Linus Torvalds 2005-04-16 2356
d7468609ee0f90 Christoph Hellwig 2024-02-19 2357 /**
d7468609ee0f90 Christoph Hellwig 2024-02-19 2358 * shmem_get_folio - find, and lock a shmem folio.
d7468609ee0f90 Christoph Hellwig 2024-02-19 2359 * @inode: inode to search
d7468609ee0f90 Christoph Hellwig 2024-02-19 2360 * @index: the page index.
d7468609ee0f90 Christoph Hellwig 2024-02-19 2361 * @foliop: pointer to the folio if found
d7468609ee0f90 Christoph Hellwig 2024-02-19 2362 * @sgp: SGP_* flags to control behavior
d7468609ee0f90 Christoph Hellwig 2024-02-19 2363 *
d7468609ee0f90 Christoph Hellwig 2024-02-19 2364 * Looks up the page cache entry at @inode & @index. If a folio is
d7468609ee0f90 Christoph Hellwig 2024-02-19 2365 * present, it is returned locked with an increased refcount.
d7468609ee0f90 Christoph Hellwig 2024-02-19 2366 *
9d8b36744935f8 Christoph Hellwig 2024-02-19 2367 * If the caller modifies data in the folio, it must call folio_mark_dirty()
9d8b36744935f8 Christoph Hellwig 2024-02-19 2368 * before unlocking the folio to ensure that the folio is not reclaimed.
9d8b36744935f8 Christoph Hellwig 2024-02-19 2369 * There is no need to reserve space before calling folio_mark_dirty().
9d8b36744935f8 Christoph Hellwig 2024-02-19 2370 *
d7468609ee0f90 Christoph Hellwig 2024-02-19 2371 * When no folio is found, the behavior depends on @sgp:
8d4dd9d741c330 Akira Yokosawa 2024-02-27 2372 * - for SGP_READ, *@foliop is %NULL and 0 is returned
8d4dd9d741c330 Akira Yokosawa 2024-02-27 2373 * - for SGP_NOALLOC, *@foliop is %NULL and -ENOENT is returned
d7468609ee0f90 Christoph Hellwig 2024-02-19 2374 * - for all other flags a new folio is allocated, inserted into the
d7468609ee0f90 Christoph Hellwig 2024-02-19 2375 * page cache and returned locked in @foliop.
d7468609ee0f90 Christoph Hellwig 2024-02-19 2376 *
d7468609ee0f90 Christoph Hellwig 2024-02-19 2377 * Context: May sleep.
d7468609ee0f90 Christoph Hellwig 2024-02-19 2378 * Return: 0 if successful, else a negative error code.
d7468609ee0f90 Christoph Hellwig 2024-02-19 2379 */
4e1fc793ad9892 Matthew Wilcox (Oracle 2022-09-02 2380) int shmem_get_folio(struct inode *inode, pgoff_t index, struct folio **foliop,
02efe2fbe45ffd Daniel Gomez 2024-05-15 2381 enum sgp_type sgp, size_t len)
4e1fc793ad9892 Matthew Wilcox (Oracle 2022-09-02 @2382) {
4e1fc793ad9892 Matthew Wilcox (Oracle 2022-09-02 2383) return shmem_get_folio_gfp(inode, index, foliop, sgp,
02efe2fbe45ffd Daniel Gomez 2024-05-15 2384 mapping_gfp_mask(inode->i_mapping), NULL, NULL, len);
4e1fc793ad9892 Matthew Wilcox (Oracle 2022-09-02 2385) }
d7468609ee0f90 Christoph Hellwig 2024-02-19 2386 EXPORT_SYMBOL_GPL(shmem_get_folio);
4e1fc793ad9892 Matthew Wilcox (Oracle 2022-09-02 2387)
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH 12/12] shmem: add large folio support to the write and fallocate paths
2024-05-15 5:57 ` [PATCH 12/12] shmem: add large folio support to the write and fallocate paths Daniel Gomez
@ 2024-05-15 18:59 ` kernel test robot
0 siblings, 0 replies; 19+ messages in thread
From: kernel test robot @ 2024-05-15 18:59 UTC (permalink / raw)
To: Daniel Gomez, hughd, akpm, willy, jack, mcgrof
Cc: oe-kbuild-all, linux-mm, linux-xfs, djwong, Pankaj Raghav,
dagmcr, yosryahmed, baolin.wang, ritesh.list, lsf-pc, david,
chandan.babu, linux-kernel, brauner, Daniel Gomez
Hi Daniel,
kernel test robot noticed the following build warnings:
[auto build test WARNING on akpm-mm/mm-everything]
[also build test WARNING on xfs-linux/for-next brauner-vfs/vfs.all linus/master v6.9 next-20240515]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Daniel-Gomez/splice-don-t-check-for-uptodate-if-partially-uptodate-is-impl/20240515-135925
base: https://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm.git mm-everything
patch link: https://lore.kernel.org/r/20240515055719.32577-13-da.gomez%40samsung.com
patch subject: [PATCH 12/12] shmem: add large folio support to the write and fallocate paths
config: openrisc-defconfig (https://download.01.org/0day-ci/archive/20240516/202405160245.2EBqOCyg-lkp@intel.com/config)
compiler: or1k-linux-gcc (GCC) 13.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20240516/202405160245.2EBqOCyg-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202405160245.2EBqOCyg-lkp@intel.com/
All warnings (new ones prefixed by >>):
>> mm/shmem.c:1864: warning: Function parameter or struct member 'sbinfo' not described in 'shmem_mapping_size_order'
mm/shmem.c:2427: warning: Function parameter or struct member 'len' not described in 'shmem_get_folio'
vim +1864 mm/shmem.c
1845
1846 /**
1847 * shmem_mapping_size_order - Get maximum folio order for the given file size.
1848 * @mapping: Target address_space.
1849 * @index: The page index.
1850 * @size: The suggested size of the folio to create.
1851 *
1852 * This returns a high order for folios (when supported) based on the file size
1853 * which the mapping currently allows at the given index. The index is relevant
1854 * due to alignment considerations the mapping might have. The returned order
1855 * may be less than the size passed.
1856 *
1857 * Like __filemap_get_folio order calculation.
1858 *
1859 * Return: The order.
1860 */
1861 static inline unsigned int
1862 shmem_mapping_size_order(struct address_space *mapping, pgoff_t index,
1863 size_t size, struct shmem_sb_info *sbinfo)
> 1864 {
1865 unsigned int order = ilog2(size);
1866
1867 if ((order <= PAGE_SHIFT) ||
1868 (!mapping_large_folio_support(mapping) || !sbinfo->noswap))
1869 return 0;
1870
1871 order -= PAGE_SHIFT;
1872
1873 /* If we're not aligned, allocate a smaller folio */
1874 if (index & ((1UL << order) - 1))
1875 order = __ffs(index);
1876
1877 order = min_t(size_t, order, MAX_PAGECACHE_ORDER);
1878
1879 /* Order-1 not supported due to THP dependency */
1880 return (order == 1) ? 0 : order;
1881 }
1882
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH 07/12] shmem: check if a block is uptodate before splice into pipe
2024-05-15 5:57 ` [PATCH 07/12] shmem: check if a block is uptodate before splice into pipe Daniel Gomez
@ 2024-05-16 13:19 ` kernel test robot
0 siblings, 0 replies; 19+ messages in thread
From: kernel test robot @ 2024-05-16 13:19 UTC (permalink / raw)
To: Daniel Gomez, hughd, akpm, willy, jack, mcgrof
Cc: oe-kbuild-all, linux-mm, linux-xfs, djwong, Pankaj Raghav,
dagmcr, yosryahmed, baolin.wang, ritesh.list, lsf-pc, david,
chandan.babu, linux-kernel, brauner, Daniel Gomez
Hi Daniel,
kernel test robot noticed the following build errors:
[auto build test ERROR on akpm-mm/mm-everything]
[also build test ERROR on xfs-linux/for-next brauner-vfs/vfs.all linus/master v6.9 next-20240516]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Daniel-Gomez/splice-don-t-check-for-uptodate-if-partially-uptodate-is-impl/20240515-135925
base: https://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm.git mm-everything
patch link: https://lore.kernel.org/r/20240515055719.32577-8-da.gomez%40samsung.com
patch subject: [PATCH 07/12] shmem: check if a block is uptodate before splice into pipe
config: arm-s5pv210_defconfig (https://download.01.org/0day-ci/archive/20240516/202405162045.kaXgB2n3-lkp@intel.com/config)
compiler: arm-linux-gnueabi-gcc (GCC) 13.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20240516/202405162045.kaXgB2n3-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202405162045.kaXgB2n3-lkp@intel.com/
All errors (new ones prefixed by >>):
arm-linux-gnueabi-ld: mm/shmem.o: in function `shmem_file_splice_read':
>> mm/shmem.c:3240:(.text+0x5224): undefined reference to `__aeabi_ldivmod'
vim +3240 mm/shmem.c
3174
3175 static ssize_t shmem_file_splice_read(struct file *in, loff_t *ppos,
3176 struct pipe_inode_info *pipe,
3177 size_t len, unsigned int flags)
3178 {
3179 struct inode *inode = file_inode(in);
3180 struct address_space *mapping = inode->i_mapping;
3181 struct folio *folio = NULL;
3182 size_t total_spliced = 0, used, npages, n, part;
3183 loff_t isize;
3184 int error = 0;
3185
3186 /* Work out how much data we can actually add into the pipe */
3187 used = pipe_occupancy(pipe->head, pipe->tail);
3188 npages = max_t(ssize_t, pipe->max_usage - used, 0);
3189 len = min_t(size_t, len, npages * PAGE_SIZE);
3190
3191 do {
3192 if (*ppos >= i_size_read(inode))
3193 break;
3194
3195 error = shmem_get_folio(inode, *ppos / PAGE_SIZE, &folio,
3196 SGP_READ);
3197 if (error) {
3198 if (error == -EINVAL)
3199 error = 0;
3200 break;
3201 }
3202 if (folio) {
3203 folio_unlock(folio);
3204
3205 if (folio_test_hwpoison(folio) ||
3206 (folio_test_large(folio) &&
3207 folio_test_has_hwpoisoned(folio))) {
3208 error = -EIO;
3209 break;
3210 }
3211 }
3212
3213 /*
3214 * i_size must be checked after we know the pages are Uptodate.
3215 *
3216 * Checking i_size after the check allows us to calculate
3217 * the correct value for "nr", which means the zero-filled
3218 * part of the page is not copied back to userspace (unless
3219 * another truncate extends the file - this is desired though).
3220 */
3221 isize = i_size_read(inode);
3222 if (unlikely(*ppos >= isize))
3223 break;
3224 part = min_t(loff_t, isize - *ppos, len);
3225 if (folio && folio_test_large(folio) &&
3226 folio_test_private(folio)) {
3227 unsigned long from = offset_in_folio(folio, *ppos);
3228 unsigned int bfirst = from >> inode->i_blkbits;
3229 unsigned int blast, blast_upd;
3230
3231 len = min(folio_size(folio) - from, len);
3232 blast = (from + len - 1) >> inode->i_blkbits;
3233
3234 blast_upd = sfs_get_last_block_uptodate(folio, bfirst,
3235 blast);
3236 if (blast_upd <= blast) {
3237 unsigned int bsize = 1 << inode->i_blkbits;
3238 unsigned int blks = blast_upd - bfirst + 1;
3239 unsigned int bbytes = blks << inode->i_blkbits;
> 3240 unsigned int boff = (*ppos % bsize);
3241
3242 part = min_t(loff_t, bbytes - boff, len);
3243 }
3244 }
3245
3246 if (folio && shmem_is_block_uptodate(
3247 folio, offset_in_folio(folio, *ppos) >>
3248 inode->i_blkbits)) {
3249 /*
3250 * If users can be writing to this page using arbitrary
3251 * virtual addresses, take care about potential aliasing
3252 * before reading the page on the kernel side.
3253 */
3254 if (mapping_writably_mapped(mapping))
3255 flush_dcache_folio(folio);
3256 folio_mark_accessed(folio);
3257 /*
3258 * Ok, we have the page, and it's up-to-date, so we can
3259 * now splice it into the pipe.
3260 */
3261 n = splice_folio_into_pipe(pipe, folio, *ppos, part);
3262 folio_put(folio);
3263 folio = NULL;
3264 } else {
3265 n = splice_zeropage_into_pipe(pipe, *ppos, part);
3266 }
3267
3268 if (!n)
3269 break;
3270 len -= n;
3271 total_spliced += n;
3272 *ppos += n;
3273 in->f_ra.prev_pos = *ppos;
3274 if (pipe_full(pipe->head, pipe->tail, pipe->max_usage))
3275 break;
3276
3277 cond_resched();
3278 } while (len);
3279
3280 if (folio)
3281 folio_put(folio);
3282
3283 file_accessed(in);
3284 return total_spliced ? total_spliced : error;
3285 }
3286
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH 11/12] shmem: add file length arg in shmem_get_folio() path
2024-05-15 5:57 ` [PATCH 11/12] shmem: add file length arg in shmem_get_folio() path Daniel Gomez
2024-05-15 17:47 ` kernel test robot
@ 2024-05-17 16:17 ` Darrick J. Wong
2024-05-21 11:38 ` Daniel Gomez
1 sibling, 1 reply; 19+ messages in thread
From: Darrick J. Wong @ 2024-05-17 16:17 UTC (permalink / raw)
To: Daniel Gomez
Cc: hughd, akpm, willy, jack, mcgrof, linux-mm, linux-xfs,
Pankaj Raghav, dagmcr, yosryahmed, baolin.wang, ritesh.list,
lsf-pc, david, chandan.babu, linux-kernel, brauner
On Wed, May 15, 2024 at 05:57:36AM +0000, Daniel Gomez wrote:
> In preparation for large folio in the write and fallocate paths, add
> file length argument in shmem_get_folio() path to be able to calculate
> the folio order based on the file size. Use of order-0 (PAGE_SIZE) for
> read, page cache read, and vm fault.
>
> This enables high order folios in the write and fallocate path once the
> folio order is calculated based on the length.
>
> Signed-off-by: Daniel Gomez <da.gomez@samsung.com>
> ---
> fs/xfs/scrub/xfile.c | 6 +++---
> fs/xfs/xfs_buf_mem.c | 3 ++-
> include/linux/shmem_fs.h | 2 +-
> mm/khugepaged.c | 3 ++-
> mm/shmem.c | 35 ++++++++++++++++++++---------------
> mm/userfaultfd.c | 2 +-
> 6 files changed, 29 insertions(+), 22 deletions(-)
>
> diff --git a/fs/xfs/scrub/xfile.c b/fs/xfs/scrub/xfile.c
> index 8cdd863db585..4905f5e4cb5d 100644
> --- a/fs/xfs/scrub/xfile.c
> +++ b/fs/xfs/scrub/xfile.c
> @@ -127,7 +127,7 @@ xfile_load(
> unsigned int offset;
>
> if (shmem_get_folio(inode, pos >> PAGE_SHIFT, &folio,
> - SGP_READ) < 0)
> + SGP_READ, PAGE_SIZE) < 0)
I suppose I /did/ say during LSFMM that for the current users of xfile.c
and xfs_buf_mem.c the order of the folio being returned doesn't really
matter, but why wouldn't the last argument here be "roundup_64(count,
PAGE_SIZE)" ? Shouldn't we at least hint to the page cache about the
folio order that we actually want instead of limiting it to order-0?
(Also it seems a little odd to me that the @index is in units of pgoff_t
but @len is in bytes.)
> break;
> if (!folio) {
> /*
> @@ -197,7 +197,7 @@ xfile_store(
> unsigned int offset;
>
> if (shmem_get_folio(inode, pos >> PAGE_SHIFT, &folio,
> - SGP_CACHE) < 0)
> + SGP_CACHE, PAGE_SIZE) < 0)
> break;
> if (filemap_check_wb_err(inode->i_mapping, 0)) {
> folio_unlock(folio);
> @@ -268,7 +268,7 @@ xfile_get_folio(
>
> pflags = memalloc_nofs_save();
> error = shmem_get_folio(inode, pos >> PAGE_SHIFT, &folio,
> - (flags & XFILE_ALLOC) ? SGP_CACHE : SGP_READ);
> + (flags & XFILE_ALLOC) ? SGP_CACHE : SGP_READ, PAGE_SIZE);
> memalloc_nofs_restore(pflags);
> if (error)
> return ERR_PTR(error);
> diff --git a/fs/xfs/xfs_buf_mem.c b/fs/xfs/xfs_buf_mem.c
> index 9bb2d24de709..784c81d35a1f 100644
> --- a/fs/xfs/xfs_buf_mem.c
> +++ b/fs/xfs/xfs_buf_mem.c
> @@ -149,7 +149,8 @@ xmbuf_map_page(
> return -ENOMEM;
> }
>
> - error = shmem_get_folio(inode, pos >> PAGE_SHIFT, &folio, SGP_CACHE);
> + error = shmem_get_folio(inode, pos >> PAGE_SHIFT, &folio, SGP_CACHE,
> + PAGE_SIZE);
This is ok unless someone wants to use a different XMBUF_BLOCKSIZE.
--D
> if (error)
> return error;
>
> diff --git a/include/linux/shmem_fs.h b/include/linux/shmem_fs.h
> index 3fb18f7eb73e..bc59b4a00228 100644
> --- a/include/linux/shmem_fs.h
> +++ b/include/linux/shmem_fs.h
> @@ -142,7 +142,7 @@ enum sgp_type {
> };
>
> int shmem_get_folio(struct inode *inode, pgoff_t index, struct folio **foliop,
> - enum sgp_type sgp);
> + enum sgp_type sgp, size_t len);
> struct folio *shmem_read_folio_gfp(struct address_space *mapping,
> pgoff_t index, gfp_t gfp);
>
> diff --git a/mm/khugepaged.c b/mm/khugepaged.c
> index 38830174608f..947770ded68c 100644
> --- a/mm/khugepaged.c
> +++ b/mm/khugepaged.c
> @@ -1863,7 +1863,8 @@ static int collapse_file(struct mm_struct *mm, unsigned long addr,
> xas_unlock_irq(&xas);
> /* swap in or instantiate fallocated page */
> if (shmem_get_folio(mapping->host, index,
> - &folio, SGP_NOALLOC)) {
> + &folio, SGP_NOALLOC,
> + PAGE_SIZE)) {
> result = SCAN_FAIL;
> goto xa_unlocked;
> }
> diff --git a/mm/shmem.c b/mm/shmem.c
> index d531018ffece..fcd2c9befe19 100644
> --- a/mm/shmem.c
> +++ b/mm/shmem.c
> @@ -1134,7 +1134,7 @@ static struct folio *shmem_get_partial_folio(struct inode *inode, pgoff_t index)
> * (although in some cases this is just a waste of time).
> */
> folio = NULL;
> - shmem_get_folio(inode, index, &folio, SGP_READ);
> + shmem_get_folio(inode, index, &folio, SGP_READ, PAGE_SIZE);
> return folio;
> }
>
> @@ -1844,7 +1844,7 @@ static struct folio *shmem_alloc_folio(gfp_t gfp, struct shmem_inode_info *info,
>
> static struct folio *shmem_alloc_and_add_folio(gfp_t gfp,
> struct inode *inode, pgoff_t index,
> - struct mm_struct *fault_mm, bool huge)
> + struct mm_struct *fault_mm, bool huge, size_t len)
> {
> struct address_space *mapping = inode->i_mapping;
> struct shmem_inode_info *info = SHMEM_I(inode);
> @@ -2173,7 +2173,7 @@ static int shmem_swapin_folio(struct inode *inode, pgoff_t index,
> */
> static int shmem_get_folio_gfp(struct inode *inode, pgoff_t index,
> struct folio **foliop, enum sgp_type sgp, gfp_t gfp,
> - struct vm_fault *vmf, vm_fault_t *fault_type)
> + struct vm_fault *vmf, vm_fault_t *fault_type, size_t len)
> {
> struct vm_area_struct *vma = vmf ? vmf->vma : NULL;
> struct mm_struct *fault_mm;
> @@ -2258,7 +2258,7 @@ static int shmem_get_folio_gfp(struct inode *inode, pgoff_t index,
> huge_gfp = vma_thp_gfp_mask(vma);
> huge_gfp = limit_gfp_mask(huge_gfp, gfp);
> folio = shmem_alloc_and_add_folio(huge_gfp,
> - inode, index, fault_mm, true);
> + inode, index, fault_mm, true, len);
> if (!IS_ERR(folio)) {
> count_vm_event(THP_FILE_ALLOC);
> goto alloced;
> @@ -2267,7 +2267,8 @@ static int shmem_get_folio_gfp(struct inode *inode, pgoff_t index,
> goto repeat;
> }
>
> - folio = shmem_alloc_and_add_folio(gfp, inode, index, fault_mm, false);
> + folio = shmem_alloc_and_add_folio(gfp, inode, index, fault_mm, false,
> + len);
> if (IS_ERR(folio)) {
> error = PTR_ERR(folio);
> if (error == -EEXIST)
> @@ -2377,10 +2378,10 @@ static int shmem_get_folio_gfp(struct inode *inode, pgoff_t index,
> * Return: 0 if successful, else a negative error code.
> */
> int shmem_get_folio(struct inode *inode, pgoff_t index, struct folio **foliop,
> - enum sgp_type sgp)
> + enum sgp_type sgp, size_t len)
> {
> return shmem_get_folio_gfp(inode, index, foliop, sgp,
> - mapping_gfp_mask(inode->i_mapping), NULL, NULL);
> + mapping_gfp_mask(inode->i_mapping), NULL, NULL, len);
> }
> EXPORT_SYMBOL_GPL(shmem_get_folio);
>
> @@ -2475,7 +2476,7 @@ static vm_fault_t shmem_fault(struct vm_fault *vmf)
>
> WARN_ON_ONCE(vmf->page != NULL);
> err = shmem_get_folio_gfp(inode, vmf->pgoff, &folio, SGP_CACHE,
> - gfp, vmf, &ret);
> + gfp, vmf, &ret, PAGE_SIZE);
> if (err)
> return vmf_error(err);
> if (folio) {
> @@ -2954,6 +2955,9 @@ shmem_write_begin(struct file *file, struct address_space *mapping,
> struct folio *folio;
> int ret = 0;
>
> + if (!mapping_large_folio_support(mapping))
> + len = min_t(size_t, len, PAGE_SIZE - offset_in_page(pos));
> +
> /* i_rwsem is held by caller */
> if (unlikely(info->seals & (F_SEAL_GROW |
> F_SEAL_WRITE | F_SEAL_FUTURE_WRITE))) {
> @@ -2963,7 +2967,7 @@ shmem_write_begin(struct file *file, struct address_space *mapping,
> return -EPERM;
> }
>
> - ret = shmem_get_folio(inode, index, &folio, SGP_WRITE);
> + ret = shmem_get_folio(inode, index, &folio, SGP_WRITE, len);
> if (ret)
> return ret;
>
> @@ -3083,7 +3087,7 @@ static ssize_t shmem_file_read_iter(struct kiocb *iocb, struct iov_iter *to)
> break;
> }
>
> - error = shmem_get_folio(inode, index, &folio, SGP_READ);
> + error = shmem_get_folio(inode, index, &folio, SGP_READ, PAGE_SIZE);
> if (error) {
> if (error == -EINVAL)
> error = 0;
> @@ -3260,7 +3264,7 @@ static ssize_t shmem_file_splice_read(struct file *in, loff_t *ppos,
> break;
>
> error = shmem_get_folio(inode, *ppos / PAGE_SIZE, &folio,
> - SGP_READ);
> + SGP_READ, PAGE_SIZE);
> if (error) {
> if (error == -EINVAL)
> error = 0;
> @@ -3469,7 +3473,8 @@ static long shmem_fallocate(struct file *file, int mode, loff_t offset,
> error = -ENOMEM;
> else
> error = shmem_get_folio(inode, index, &folio,
> - SGP_FALLOC);
> + SGP_FALLOC,
> + (end - index) << PAGE_SHIFT);
> if (error) {
> info->fallocend = undo_fallocend;
> /* Remove the !uptodate folios we added */
> @@ -3822,7 +3827,7 @@ static int shmem_symlink(struct mnt_idmap *idmap, struct inode *dir,
> } else {
> inode_nohighmem(inode);
> inode->i_mapping->a_ops = &shmem_aops;
> - error = shmem_get_folio(inode, 0, &folio, SGP_WRITE);
> + error = shmem_get_folio(inode, 0, &folio, SGP_WRITE, PAGE_SIZE);
> if (error)
> goto out_remove_offset;
> inode->i_op = &shmem_symlink_inode_operations;
> @@ -3868,7 +3873,7 @@ static const char *shmem_get_link(struct dentry *dentry, struct inode *inode,
> return ERR_PTR(-ECHILD);
> }
> } else {
> - error = shmem_get_folio(inode, 0, &folio, SGP_READ);
> + error = shmem_get_folio(inode, 0, &folio, SGP_READ, PAGE_SIZE);
> if (error)
> return ERR_PTR(error);
> if (!folio)
> @@ -5255,7 +5260,7 @@ struct folio *shmem_read_folio_gfp(struct address_space *mapping,
> int error;
>
> error = shmem_get_folio_gfp(inode, index, &folio, SGP_CACHE,
> - gfp, NULL, NULL);
> + gfp, NULL, NULL, PAGE_SIZE);
> if (error)
> return ERR_PTR(error);
>
> diff --git a/mm/userfaultfd.c b/mm/userfaultfd.c
> index 3c3539c573e7..540a0c2d4325 100644
> --- a/mm/userfaultfd.c
> +++ b/mm/userfaultfd.c
> @@ -359,7 +359,7 @@ static int mfill_atomic_pte_continue(pmd_t *dst_pmd,
> struct page *page;
> int ret;
>
> - ret = shmem_get_folio(inode, pgoff, &folio, SGP_NOALLOC);
> + ret = shmem_get_folio(inode, pgoff, &folio, SGP_NOALLOC, PAGE_SIZE);
> /* Our caller expects us to return -EFAULT if we failed to find folio */
> if (ret == -ENOENT)
> ret = -EFAULT;
> --
> 2.43.0
>
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH 11/12] shmem: add file length arg in shmem_get_folio() path
2024-05-17 16:17 ` Darrick J. Wong
@ 2024-05-21 11:38 ` Daniel Gomez
2024-05-21 16:36 ` Darrick J. Wong
0 siblings, 1 reply; 19+ messages in thread
From: Daniel Gomez @ 2024-05-21 11:38 UTC (permalink / raw)
To: Darrick J. Wong
Cc: hughd, akpm, willy, jack, mcgrof, linux-mm, linux-xfs,
Pankaj Raghav, dagmcr, yosryahmed, baolin.wang, ritesh.list,
lsf-pc, david, chandan.babu, linux-kernel, brauner
On Fri, May 17, 2024 at 09:17:41AM -0700, Darrick J. Wong wrote:
> On Wed, May 15, 2024 at 05:57:36AM +0000, Daniel Gomez wrote:
> > In preparation for large folio in the write and fallocate paths, add
> > file length argument in shmem_get_folio() path to be able to calculate
> > the folio order based on the file size. Use of order-0 (PAGE_SIZE) for
> > read, page cache read, and vm fault.
> >
> > This enables high order folios in the write and fallocate path once the
> > folio order is calculated based on the length.
> >
> > Signed-off-by: Daniel Gomez <da.gomez@samsung.com>
> > ---
> > fs/xfs/scrub/xfile.c | 6 +++---
> > fs/xfs/xfs_buf_mem.c | 3 ++-
> > include/linux/shmem_fs.h | 2 +-
> > mm/khugepaged.c | 3 ++-
> > mm/shmem.c | 35 ++++++++++++++++++++---------------
> > mm/userfaultfd.c | 2 +-
> > 6 files changed, 29 insertions(+), 22 deletions(-)
> >
> > diff --git a/fs/xfs/scrub/xfile.c b/fs/xfs/scrub/xfile.c
> > index 8cdd863db585..4905f5e4cb5d 100644
> > --- a/fs/xfs/scrub/xfile.c
> > +++ b/fs/xfs/scrub/xfile.c
> > @@ -127,7 +127,7 @@ xfile_load(
> > unsigned int offset;
> >
> > if (shmem_get_folio(inode, pos >> PAGE_SHIFT, &folio,
> > - SGP_READ) < 0)
> > + SGP_READ, PAGE_SIZE) < 0)
>
> I suppose I /did/ say during LSFMM that for the current users of xfile.c
> and xfs_buf_mem.c the order of the folio being returned doesn't really
I not sure if I understood you well. Could you please elaborate on this?
> matter, but why wouldn't the last argument here be "roundup_64(count,
> PAGE_SIZE)" ? Shouldn't we at least hint to the page cache about the
> folio order that we actually want instead of limiting it to order-0?
For v2, I'll include your suggestions. I think we can also enable large folios
in xfile_get_folio(), please check below:
diff --git a/fs/xfs/scrub/xfile.c b/fs/xfs/scrub/xfile.c
index 8cdd863db585..df8b495b4939 100644
--- a/fs/xfs/scrub/xfile.c
+++ b/fs/xfs/scrub/xfile.c
@@ -127,7 +127,7 @@ xfile_load(
unsigned int offset;
if (shmem_get_folio(inode, pos >> PAGE_SHIFT, &folio,
- SGP_READ) < 0)
+ SGP_READ, roundup_64(count, PAGE_SIZE)) < 0)
break;
if (!folio) {
/*
@@ -197,7 +197,7 @@ xfile_store(
unsigned int offset;
if (shmem_get_folio(inode, pos >> PAGE_SHIFT, &folio,
- SGP_CACHE) < 0)
+ SGP_CACHE, roundup_64(count, PAGE_SIZE)) < 0)
break;
if (filemap_check_wb_err(inode->i_mapping, 0)) {
folio_unlock(folio);
@@ -268,7 +268,8 @@ xfile_get_folio(
pflags = memalloc_nofs_save();
error = shmem_get_folio(inode, pos >> PAGE_SHIFT, &folio,
- (flags & XFILE_ALLOC) ? SGP_CACHE : SGP_READ);
+ (flags & XFILE_ALLOC) ? SGP_CACHE : SGP_READ,
+ roundup_64(i_size_read(inode), PAGE_SIZE));
memalloc_nofs_restore(pflags);
if (error)
return ERR_PTR(error);
>
> (Also it seems a little odd to me that the @index is in units of pgoff_t
> but @len is in bytes.)
I extended the shmem_get_folio() with @len to calculate folio order based on
size (bytes). This is sent to ilog2() although I'm planning to use get_order()
instead (after fixing the issues mentioned during the discussion). @index is
used for __ffs() (same as in filemap).
Would you use lofft for @len instead? Or what's your suggestion?
Thanks,
Daniel
>
> > break;
> > if (!folio) {
> > /*
> > @@ -197,7 +197,7 @@ xfile_store(
> > unsigned int offset;
> >
> > if (shmem_get_folio(inode, pos >> PAGE_SHIFT, &folio,
> > - SGP_CACHE) < 0)
> > + SGP_CACHE, PAGE_SIZE) < 0)
> > break;
> > if (filemap_check_wb_err(inode->i_mapping, 0)) {
> > folio_unlock(folio);
> > @@ -268,7 +268,7 @@ xfile_get_folio(
> >
> > pflags = memalloc_nofs_save();
> > error = shmem_get_folio(inode, pos >> PAGE_SHIFT, &folio,
> > - (flags & XFILE_ALLOC) ? SGP_CACHE : SGP_READ);
> > + (flags & XFILE_ALLOC) ? SGP_CACHE : SGP_READ, PAGE_SIZE);
> > memalloc_nofs_restore(pflags);
> > if (error)
> > return ERR_PTR(error);
> > diff --git a/fs/xfs/xfs_buf_mem.c b/fs/xfs/xfs_buf_mem.c
> > index 9bb2d24de709..784c81d35a1f 100644
> > --- a/fs/xfs/xfs_buf_mem.c
> > +++ b/fs/xfs/xfs_buf_mem.c
> > @@ -149,7 +149,8 @@ xmbuf_map_page(
> > return -ENOMEM;
> > }
> >
> > - error = shmem_get_folio(inode, pos >> PAGE_SHIFT, &folio, SGP_CACHE);
> > + error = shmem_get_folio(inode, pos >> PAGE_SHIFT, &folio, SGP_CACHE,
> > + PAGE_SIZE);
>
> This is ok unless someone wants to use a different XMBUF_BLOCKSIZE.
>
> --D
>
> > if (error)
> > return error;
> >
> > diff --git a/include/linux/shmem_fs.h b/include/linux/shmem_fs.h
> > index 3fb18f7eb73e..bc59b4a00228 100644
> > --- a/include/linux/shmem_fs.h
> > +++ b/include/linux/shmem_fs.h
> > @@ -142,7 +142,7 @@ enum sgp_type {
> > };
> >
> > int shmem_get_folio(struct inode *inode, pgoff_t index, struct folio **foliop,
> > - enum sgp_type sgp);
> > + enum sgp_type sgp, size_t len);
> > struct folio *shmem_read_folio_gfp(struct address_space *mapping,
> > pgoff_t index, gfp_t gfp);
> >
> > diff --git a/mm/khugepaged.c b/mm/khugepaged.c
> > index 38830174608f..947770ded68c 100644
> > --- a/mm/khugepaged.c
> > +++ b/mm/khugepaged.c
> > @@ -1863,7 +1863,8 @@ static int collapse_file(struct mm_struct *mm, unsigned long addr,
> > xas_unlock_irq(&xas);
> > /* swap in or instantiate fallocated page */
> > if (shmem_get_folio(mapping->host, index,
> > - &folio, SGP_NOALLOC)) {
> > + &folio, SGP_NOALLOC,
> > + PAGE_SIZE)) {
> > result = SCAN_FAIL;
> > goto xa_unlocked;
> > }
> > diff --git a/mm/shmem.c b/mm/shmem.c
> > index d531018ffece..fcd2c9befe19 100644
> > --- a/mm/shmem.c
> > +++ b/mm/shmem.c
> > @@ -1134,7 +1134,7 @@ static struct folio *shmem_get_partial_folio(struct inode *inode, pgoff_t index)
> > * (although in some cases this is just a waste of time).
> > */
> > folio = NULL;
> > - shmem_get_folio(inode, index, &folio, SGP_READ);
> > + shmem_get_folio(inode, index, &folio, SGP_READ, PAGE_SIZE);
> > return folio;
> > }
> >
> > @@ -1844,7 +1844,7 @@ static struct folio *shmem_alloc_folio(gfp_t gfp, struct shmem_inode_info *info,
> >
> > static struct folio *shmem_alloc_and_add_folio(gfp_t gfp,
> > struct inode *inode, pgoff_t index,
> > - struct mm_struct *fault_mm, bool huge)
> > + struct mm_struct *fault_mm, bool huge, size_t len)
> > {
> > struct address_space *mapping = inode->i_mapping;
> > struct shmem_inode_info *info = SHMEM_I(inode);
> > @@ -2173,7 +2173,7 @@ static int shmem_swapin_folio(struct inode *inode, pgoff_t index,
> > */
> > static int shmem_get_folio_gfp(struct inode *inode, pgoff_t index,
> > struct folio **foliop, enum sgp_type sgp, gfp_t gfp,
> > - struct vm_fault *vmf, vm_fault_t *fault_type)
> > + struct vm_fault *vmf, vm_fault_t *fault_type, size_t len)
> > {
> > struct vm_area_struct *vma = vmf ? vmf->vma : NULL;
> > struct mm_struct *fault_mm;
> > @@ -2258,7 +2258,7 @@ static int shmem_get_folio_gfp(struct inode *inode, pgoff_t index,
> > huge_gfp = vma_thp_gfp_mask(vma);
> > huge_gfp = limit_gfp_mask(huge_gfp, gfp);
> > folio = shmem_alloc_and_add_folio(huge_gfp,
> > - inode, index, fault_mm, true);
> > + inode, index, fault_mm, true, len);
> > if (!IS_ERR(folio)) {
> > count_vm_event(THP_FILE_ALLOC);
> > goto alloced;
> > @@ -2267,7 +2267,8 @@ static int shmem_get_folio_gfp(struct inode *inode, pgoff_t index,
> > goto repeat;
> > }
> >
> > - folio = shmem_alloc_and_add_folio(gfp, inode, index, fault_mm, false);
> > + folio = shmem_alloc_and_add_folio(gfp, inode, index, fault_mm, false,
> > + len);
> > if (IS_ERR(folio)) {
> > error = PTR_ERR(folio);
> > if (error == -EEXIST)
> > @@ -2377,10 +2378,10 @@ static int shmem_get_folio_gfp(struct inode *inode, pgoff_t index,
> > * Return: 0 if successful, else a negative error code.
> > */
> > int shmem_get_folio(struct inode *inode, pgoff_t index, struct folio **foliop,
> > - enum sgp_type sgp)
> > + enum sgp_type sgp, size_t len)
> > {
> > return shmem_get_folio_gfp(inode, index, foliop, sgp,
> > - mapping_gfp_mask(inode->i_mapping), NULL, NULL);
> > + mapping_gfp_mask(inode->i_mapping), NULL, NULL, len);
> > }
> > EXPORT_SYMBOL_GPL(shmem_get_folio);
> >
> > @@ -2475,7 +2476,7 @@ static vm_fault_t shmem_fault(struct vm_fault *vmf)
> >
> > WARN_ON_ONCE(vmf->page != NULL);
> > err = shmem_get_folio_gfp(inode, vmf->pgoff, &folio, SGP_CACHE,
> > - gfp, vmf, &ret);
> > + gfp, vmf, &ret, PAGE_SIZE);
> > if (err)
> > return vmf_error(err);
> > if (folio) {
> > @@ -2954,6 +2955,9 @@ shmem_write_begin(struct file *file, struct address_space *mapping,
> > struct folio *folio;
> > int ret = 0;
> >
> > + if (!mapping_large_folio_support(mapping))
> > + len = min_t(size_t, len, PAGE_SIZE - offset_in_page(pos));
> > +
> > /* i_rwsem is held by caller */
> > if (unlikely(info->seals & (F_SEAL_GROW |
> > F_SEAL_WRITE | F_SEAL_FUTURE_WRITE))) {
> > @@ -2963,7 +2967,7 @@ shmem_write_begin(struct file *file, struct address_space *mapping,
> > return -EPERM;
> > }
> >
> > - ret = shmem_get_folio(inode, index, &folio, SGP_WRITE);
> > + ret = shmem_get_folio(inode, index, &folio, SGP_WRITE, len);
> > if (ret)
> > return ret;
> >
> > @@ -3083,7 +3087,7 @@ static ssize_t shmem_file_read_iter(struct kiocb *iocb, struct iov_iter *to)
> > break;
> > }
> >
> > - error = shmem_get_folio(inode, index, &folio, SGP_READ);
> > + error = shmem_get_folio(inode, index, &folio, SGP_READ, PAGE_SIZE);
> > if (error) {
> > if (error == -EINVAL)
> > error = 0;
> > @@ -3260,7 +3264,7 @@ static ssize_t shmem_file_splice_read(struct file *in, loff_t *ppos,
> > break;
> >
> > error = shmem_get_folio(inode, *ppos / PAGE_SIZE, &folio,
> > - SGP_READ);
> > + SGP_READ, PAGE_SIZE);
> > if (error) {
> > if (error == -EINVAL)
> > error = 0;
> > @@ -3469,7 +3473,8 @@ static long shmem_fallocate(struct file *file, int mode, loff_t offset,
> > error = -ENOMEM;
> > else
> > error = shmem_get_folio(inode, index, &folio,
> > - SGP_FALLOC);
> > + SGP_FALLOC,
> > + (end - index) << PAGE_SHIFT);
> > if (error) {
> > info->fallocend = undo_fallocend;
> > /* Remove the !uptodate folios we added */
> > @@ -3822,7 +3827,7 @@ static int shmem_symlink(struct mnt_idmap *idmap, struct inode *dir,
> > } else {
> > inode_nohighmem(inode);
> > inode->i_mapping->a_ops = &shmem_aops;
> > - error = shmem_get_folio(inode, 0, &folio, SGP_WRITE);
> > + error = shmem_get_folio(inode, 0, &folio, SGP_WRITE, PAGE_SIZE);
> > if (error)
> > goto out_remove_offset;
> > inode->i_op = &shmem_symlink_inode_operations;
> > @@ -3868,7 +3873,7 @@ static const char *shmem_get_link(struct dentry *dentry, struct inode *inode,
> > return ERR_PTR(-ECHILD);
> > }
> > } else {
> > - error = shmem_get_folio(inode, 0, &folio, SGP_READ);
> > + error = shmem_get_folio(inode, 0, &folio, SGP_READ, PAGE_SIZE);
> > if (error)
> > return ERR_PTR(error);
> > if (!folio)
> > @@ -5255,7 +5260,7 @@ struct folio *shmem_read_folio_gfp(struct address_space *mapping,
> > int error;
> >
> > error = shmem_get_folio_gfp(inode, index, &folio, SGP_CACHE,
> > - gfp, NULL, NULL);
> > + gfp, NULL, NULL, PAGE_SIZE);
> > if (error)
> > return ERR_PTR(error);
> >
> > diff --git a/mm/userfaultfd.c b/mm/userfaultfd.c
> > index 3c3539c573e7..540a0c2d4325 100644
> > --- a/mm/userfaultfd.c
> > +++ b/mm/userfaultfd.c
> > @@ -359,7 +359,7 @@ static int mfill_atomic_pte_continue(pmd_t *dst_pmd,
> > struct page *page;
> > int ret;
> >
> > - ret = shmem_get_folio(inode, pgoff, &folio, SGP_NOALLOC);
> > + ret = shmem_get_folio(inode, pgoff, &folio, SGP_NOALLOC, PAGE_SIZE);
> > /* Our caller expects us to return -EFAULT if we failed to find folio */
> > if (ret == -ENOENT)
> > ret = -EFAULT;
> > --
> > 2.43.0
> >
^ permalink raw reply related [flat|nested] 19+ messages in thread
* Re: [PATCH 11/12] shmem: add file length arg in shmem_get_folio() path
2024-05-21 11:38 ` Daniel Gomez
@ 2024-05-21 16:36 ` Darrick J. Wong
0 siblings, 0 replies; 19+ messages in thread
From: Darrick J. Wong @ 2024-05-21 16:36 UTC (permalink / raw)
To: Daniel Gomez
Cc: hughd, akpm, willy, jack, mcgrof, linux-mm, linux-xfs,
Pankaj Raghav, dagmcr, yosryahmed, baolin.wang, ritesh.list,
lsf-pc, david, chandan.babu, linux-kernel, brauner
On Tue, May 21, 2024 at 11:38:33AM +0000, Daniel Gomez wrote:
> On Fri, May 17, 2024 at 09:17:41AM -0700, Darrick J. Wong wrote:
> > On Wed, May 15, 2024 at 05:57:36AM +0000, Daniel Gomez wrote:
> > > In preparation for large folio in the write and fallocate paths, add
> > > file length argument in shmem_get_folio() path to be able to calculate
> > > the folio order based on the file size. Use of order-0 (PAGE_SIZE) for
> > > read, page cache read, and vm fault.
> > >
> > > This enables high order folios in the write and fallocate path once the
> > > folio order is calculated based on the length.
> > >
> > > Signed-off-by: Daniel Gomez <da.gomez@samsung.com>
> > > ---
> > > fs/xfs/scrub/xfile.c | 6 +++---
> > > fs/xfs/xfs_buf_mem.c | 3 ++-
> > > include/linux/shmem_fs.h | 2 +-
> > > mm/khugepaged.c | 3 ++-
> > > mm/shmem.c | 35 ++++++++++++++++++++---------------
> > > mm/userfaultfd.c | 2 +-
> > > 6 files changed, 29 insertions(+), 22 deletions(-)
> > >
> > > diff --git a/fs/xfs/scrub/xfile.c b/fs/xfs/scrub/xfile.c
> > > index 8cdd863db585..4905f5e4cb5d 100644
> > > --- a/fs/xfs/scrub/xfile.c
> > > +++ b/fs/xfs/scrub/xfile.c
> > > @@ -127,7 +127,7 @@ xfile_load(
> > > unsigned int offset;
> > >
> > > if (shmem_get_folio(inode, pos >> PAGE_SHIFT, &folio,
> > > - SGP_READ) < 0)
> > > + SGP_READ, PAGE_SIZE) < 0)
> >
> > I suppose I /did/ say during LSFMM that for the current users of xfile.c
> > and xfs_buf_mem.c the order of the folio being returned doesn't really
> I not sure if I understood you well. Could you please elaborate on this?
Yes, I'll restate what I said in the session last week for those who
weren't there:
Currently, xfile.c and xfs_buf_mem.c are only used by online repair to
stage a recordset while rebuilding an ondisk btree index. IOWs, they're
ephemeral, so we don't care or need to optimize folio sizing. Some day
they might be adapted for longer-term usage though, so we might as well
try not to leave too many papercuts.
xfs_buf_mem.c creates in-memory btrees that mimic the ondisk btrees,
albeit with blocksize == PAGE_SIZE, regardless of the fs blocksize.
For this case we probably aren't ever going to care about large folios.
xfile.c is currently used to store fixed-size recordsets, names for
rebuilding directories, and name/value pairs for rebuilding xattr
structures. Records aren't allowed to be larger than PAGE_SIZE, names
cannot be larger than MAXNAMELEN (255), and xattr values can't be larger
than 64k.
For that last case maybe it might be nice to get a large folio to reduce
processing overhead, but huge xattrs aren't that common.
> > matter, but why wouldn't the last argument here be "roundup_64(count,
> > PAGE_SIZE)" ? Shouldn't we at least hint to the page cache about the
> > folio order that we actually want instead of limiting it to order-0?
>
> For v2, I'll include your suggestions. I think we can also enable large folios
> in xfile_get_folio(), please check below:
>
> diff --git a/fs/xfs/scrub/xfile.c b/fs/xfs/scrub/xfile.c
> index 8cdd863db585..df8b495b4939 100644
> --- a/fs/xfs/scrub/xfile.c
> +++ b/fs/xfs/scrub/xfile.c
> @@ -127,7 +127,7 @@ xfile_load(
> unsigned int offset;
>
> if (shmem_get_folio(inode, pos >> PAGE_SHIFT, &folio,
> - SGP_READ) < 0)
> + SGP_READ, roundup_64(count, PAGE_SIZE)) < 0)
> break;
> if (!folio) {
> /*
> @@ -197,7 +197,7 @@ xfile_store(
> unsigned int offset;
>
> if (shmem_get_folio(inode, pos >> PAGE_SHIFT, &folio,
> - SGP_CACHE) < 0)
> + SGP_CACHE, roundup_64(count, PAGE_SIZE)) < 0)
> break;
> if (filemap_check_wb_err(inode->i_mapping, 0)) {
> folio_unlock(folio);
> @@ -268,7 +268,8 @@ xfile_get_folio(
>
> pflags = memalloc_nofs_save();
> error = shmem_get_folio(inode, pos >> PAGE_SHIFT, &folio,
> - (flags & XFILE_ALLOC) ? SGP_CACHE : SGP_READ);
> + (flags & XFILE_ALLOC) ? SGP_CACHE : SGP_READ,
> + roundup_64(i_size_read(inode), PAGE_SIZE));
I'm not sure why you picked i_size_read here; the xfile could be several
gigabytes long. xfile_get_folio want to look at a subset of the xfile,
not all of it.
roundup_64(len, PAGE_SIZE) perhaps?
Also, should the rounding be done inside the shmem code so that callers
don't have to know about that detail?
> memalloc_nofs_restore(pflags);
> if (error)
> return ERR_PTR(error);
>
> >
> > (Also it seems a little odd to me that the @index is in units of pgoff_t
> > but @len is in bytes.)
>
> I extended the shmem_get_folio() with @len to calculate folio order based on
> size (bytes). This is sent to ilog2() although I'm planning to use get_order()
> instead (after fixing the issues mentioned during the discussion). @index is
> used for __ffs() (same as in filemap).
>
> Would you use lofft for @len instead? Or what's your suggestion?
I was reacting to @index, not @len. I might've shifted @index to
"loff_t pos" but looking at the existing callsites it doesn't seem worth
the churn.
--D
> Thanks,
> Daniel
>
> >
> > > break;
> > > if (!folio) {
> > > /*
> > > @@ -197,7 +197,7 @@ xfile_store(
> > > unsigned int offset;
> > >
> > > if (shmem_get_folio(inode, pos >> PAGE_SHIFT, &folio,
> > > - SGP_CACHE) < 0)
> > > + SGP_CACHE, PAGE_SIZE) < 0)
> > > break;
> > > if (filemap_check_wb_err(inode->i_mapping, 0)) {
> > > folio_unlock(folio);
> > > @@ -268,7 +268,7 @@ xfile_get_folio(
> > >
> > > pflags = memalloc_nofs_save();
> > > error = shmem_get_folio(inode, pos >> PAGE_SHIFT, &folio,
> > > - (flags & XFILE_ALLOC) ? SGP_CACHE : SGP_READ);
> > > + (flags & XFILE_ALLOC) ? SGP_CACHE : SGP_READ, PAGE_SIZE);
> > > memalloc_nofs_restore(pflags);
> > > if (error)
> > > return ERR_PTR(error);
> > > diff --git a/fs/xfs/xfs_buf_mem.c b/fs/xfs/xfs_buf_mem.c
> > > index 9bb2d24de709..784c81d35a1f 100644
> > > --- a/fs/xfs/xfs_buf_mem.c
> > > +++ b/fs/xfs/xfs_buf_mem.c
> > > @@ -149,7 +149,8 @@ xmbuf_map_page(
> > > return -ENOMEM;
> > > }
> > >
> > > - error = shmem_get_folio(inode, pos >> PAGE_SHIFT, &folio, SGP_CACHE);
> > > + error = shmem_get_folio(inode, pos >> PAGE_SHIFT, &folio, SGP_CACHE,
> > > + PAGE_SIZE);
> >
> > This is ok unless someone wants to use a different XMBUF_BLOCKSIZE.
> >
> > --D
> >
> > > if (error)
> > > return error;
> > >
> > > diff --git a/include/linux/shmem_fs.h b/include/linux/shmem_fs.h
> > > index 3fb18f7eb73e..bc59b4a00228 100644
> > > --- a/include/linux/shmem_fs.h
> > > +++ b/include/linux/shmem_fs.h
> > > @@ -142,7 +142,7 @@ enum sgp_type {
> > > };
> > >
> > > int shmem_get_folio(struct inode *inode, pgoff_t index, struct folio **foliop,
> > > - enum sgp_type sgp);
> > > + enum sgp_type sgp, size_t len);
> > > struct folio *shmem_read_folio_gfp(struct address_space *mapping,
> > > pgoff_t index, gfp_t gfp);
> > >
> > > diff --git a/mm/khugepaged.c b/mm/khugepaged.c
> > > index 38830174608f..947770ded68c 100644
> > > --- a/mm/khugepaged.c
> > > +++ b/mm/khugepaged.c
> > > @@ -1863,7 +1863,8 @@ static int collapse_file(struct mm_struct *mm, unsigned long addr,
> > > xas_unlock_irq(&xas);
> > > /* swap in or instantiate fallocated page */
> > > if (shmem_get_folio(mapping->host, index,
> > > - &folio, SGP_NOALLOC)) {
> > > + &folio, SGP_NOALLOC,
> > > + PAGE_SIZE)) {
> > > result = SCAN_FAIL;
> > > goto xa_unlocked;
> > > }
> > > diff --git a/mm/shmem.c b/mm/shmem.c
> > > index d531018ffece..fcd2c9befe19 100644
> > > --- a/mm/shmem.c
> > > +++ b/mm/shmem.c
> > > @@ -1134,7 +1134,7 @@ static struct folio *shmem_get_partial_folio(struct inode *inode, pgoff_t index)
> > > * (although in some cases this is just a waste of time).
> > > */
> > > folio = NULL;
> > > - shmem_get_folio(inode, index, &folio, SGP_READ);
> > > + shmem_get_folio(inode, index, &folio, SGP_READ, PAGE_SIZE);
> > > return folio;
> > > }
> > >
> > > @@ -1844,7 +1844,7 @@ static struct folio *shmem_alloc_folio(gfp_t gfp, struct shmem_inode_info *info,
> > >
> > > static struct folio *shmem_alloc_and_add_folio(gfp_t gfp,
> > > struct inode *inode, pgoff_t index,
> > > - struct mm_struct *fault_mm, bool huge)
> > > + struct mm_struct *fault_mm, bool huge, size_t len)
> > > {
> > > struct address_space *mapping = inode->i_mapping;
> > > struct shmem_inode_info *info = SHMEM_I(inode);
> > > @@ -2173,7 +2173,7 @@ static int shmem_swapin_folio(struct inode *inode, pgoff_t index,
> > > */
> > > static int shmem_get_folio_gfp(struct inode *inode, pgoff_t index,
> > > struct folio **foliop, enum sgp_type sgp, gfp_t gfp,
> > > - struct vm_fault *vmf, vm_fault_t *fault_type)
> > > + struct vm_fault *vmf, vm_fault_t *fault_type, size_t len)
> > > {
> > > struct vm_area_struct *vma = vmf ? vmf->vma : NULL;
> > > struct mm_struct *fault_mm;
> > > @@ -2258,7 +2258,7 @@ static int shmem_get_folio_gfp(struct inode *inode, pgoff_t index,
> > > huge_gfp = vma_thp_gfp_mask(vma);
> > > huge_gfp = limit_gfp_mask(huge_gfp, gfp);
> > > folio = shmem_alloc_and_add_folio(huge_gfp,
> > > - inode, index, fault_mm, true);
> > > + inode, index, fault_mm, true, len);
> > > if (!IS_ERR(folio)) {
> > > count_vm_event(THP_FILE_ALLOC);
> > > goto alloced;
> > > @@ -2267,7 +2267,8 @@ static int shmem_get_folio_gfp(struct inode *inode, pgoff_t index,
> > > goto repeat;
> > > }
> > >
> > > - folio = shmem_alloc_and_add_folio(gfp, inode, index, fault_mm, false);
> > > + folio = shmem_alloc_and_add_folio(gfp, inode, index, fault_mm, false,
> > > + len);
> > > if (IS_ERR(folio)) {
> > > error = PTR_ERR(folio);
> > > if (error == -EEXIST)
> > > @@ -2377,10 +2378,10 @@ static int shmem_get_folio_gfp(struct inode *inode, pgoff_t index,
> > > * Return: 0 if successful, else a negative error code.
> > > */
> > > int shmem_get_folio(struct inode *inode, pgoff_t index, struct folio **foliop,
> > > - enum sgp_type sgp)
> > > + enum sgp_type sgp, size_t len)
> > > {
> > > return shmem_get_folio_gfp(inode, index, foliop, sgp,
> > > - mapping_gfp_mask(inode->i_mapping), NULL, NULL);
> > > + mapping_gfp_mask(inode->i_mapping), NULL, NULL, len);
> > > }
> > > EXPORT_SYMBOL_GPL(shmem_get_folio);
> > >
> > > @@ -2475,7 +2476,7 @@ static vm_fault_t shmem_fault(struct vm_fault *vmf)
> > >
> > > WARN_ON_ONCE(vmf->page != NULL);
> > > err = shmem_get_folio_gfp(inode, vmf->pgoff, &folio, SGP_CACHE,
> > > - gfp, vmf, &ret);
> > > + gfp, vmf, &ret, PAGE_SIZE);
> > > if (err)
> > > return vmf_error(err);
> > > if (folio) {
> > > @@ -2954,6 +2955,9 @@ shmem_write_begin(struct file *file, struct address_space *mapping,
> > > struct folio *folio;
> > > int ret = 0;
> > >
> > > + if (!mapping_large_folio_support(mapping))
> > > + len = min_t(size_t, len, PAGE_SIZE - offset_in_page(pos));
> > > +
> > > /* i_rwsem is held by caller */
> > > if (unlikely(info->seals & (F_SEAL_GROW |
> > > F_SEAL_WRITE | F_SEAL_FUTURE_WRITE))) {
> > > @@ -2963,7 +2967,7 @@ shmem_write_begin(struct file *file, struct address_space *mapping,
> > > return -EPERM;
> > > }
> > >
> > > - ret = shmem_get_folio(inode, index, &folio, SGP_WRITE);
> > > + ret = shmem_get_folio(inode, index, &folio, SGP_WRITE, len);
> > > if (ret)
> > > return ret;
> > >
> > > @@ -3083,7 +3087,7 @@ static ssize_t shmem_file_read_iter(struct kiocb *iocb, struct iov_iter *to)
> > > break;
> > > }
> > >
> > > - error = shmem_get_folio(inode, index, &folio, SGP_READ);
> > > + error = shmem_get_folio(inode, index, &folio, SGP_READ, PAGE_SIZE);
> > > if (error) {
> > > if (error == -EINVAL)
> > > error = 0;
> > > @@ -3260,7 +3264,7 @@ static ssize_t shmem_file_splice_read(struct file *in, loff_t *ppos,
> > > break;
> > >
> > > error = shmem_get_folio(inode, *ppos / PAGE_SIZE, &folio,
> > > - SGP_READ);
> > > + SGP_READ, PAGE_SIZE);
> > > if (error) {
> > > if (error == -EINVAL)
> > > error = 0;
> > > @@ -3469,7 +3473,8 @@ static long shmem_fallocate(struct file *file, int mode, loff_t offset,
> > > error = -ENOMEM;
> > > else
> > > error = shmem_get_folio(inode, index, &folio,
> > > - SGP_FALLOC);
> > > + SGP_FALLOC,
> > > + (end - index) << PAGE_SHIFT);
> > > if (error) {
> > > info->fallocend = undo_fallocend;
> > > /* Remove the !uptodate folios we added */
> > > @@ -3822,7 +3827,7 @@ static int shmem_symlink(struct mnt_idmap *idmap, struct inode *dir,
> > > } else {
> > > inode_nohighmem(inode);
> > > inode->i_mapping->a_ops = &shmem_aops;
> > > - error = shmem_get_folio(inode, 0, &folio, SGP_WRITE);
> > > + error = shmem_get_folio(inode, 0, &folio, SGP_WRITE, PAGE_SIZE);
> > > if (error)
> > > goto out_remove_offset;
> > > inode->i_op = &shmem_symlink_inode_operations;
> > > @@ -3868,7 +3873,7 @@ static const char *shmem_get_link(struct dentry *dentry, struct inode *inode,
> > > return ERR_PTR(-ECHILD);
> > > }
> > > } else {
> > > - error = shmem_get_folio(inode, 0, &folio, SGP_READ);
> > > + error = shmem_get_folio(inode, 0, &folio, SGP_READ, PAGE_SIZE);
> > > if (error)
> > > return ERR_PTR(error);
> > > if (!folio)
> > > @@ -5255,7 +5260,7 @@ struct folio *shmem_read_folio_gfp(struct address_space *mapping,
> > > int error;
> > >
> > > error = shmem_get_folio_gfp(inode, index, &folio, SGP_CACHE,
> > > - gfp, NULL, NULL);
> > > + gfp, NULL, NULL, PAGE_SIZE);
> > > if (error)
> > > return ERR_PTR(error);
> > >
> > > diff --git a/mm/userfaultfd.c b/mm/userfaultfd.c
> > > index 3c3539c573e7..540a0c2d4325 100644
> > > --- a/mm/userfaultfd.c
> > > +++ b/mm/userfaultfd.c
> > > @@ -359,7 +359,7 @@ static int mfill_atomic_pte_continue(pmd_t *dst_pmd,
> > > struct page *page;
> > > int ret;
> > >
> > > - ret = shmem_get_folio(inode, pgoff, &folio, SGP_NOALLOC);
> > > + ret = shmem_get_folio(inode, pgoff, &folio, SGP_NOALLOC, PAGE_SIZE);
> > > /* Our caller expects us to return -EFAULT if we failed to find folio */
> > > if (ret == -ENOENT)
> > > ret = -EFAULT;
> > > --
> > > 2.43.0
> > >
^ permalink raw reply [flat|nested] 19+ messages in thread
end of thread, other threads:[~2024-05-21 16:36 UTC | newest]
Thread overview: 19+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
[not found] <CGME20240515055723eucas1p11bf14732f7fac943e688369ff7765f79@eucas1p1.samsung.com>
2024-05-15 5:57 ` [PATCH 00/12] [LSF/MM/BPF RFC] shmem/tmpfs: add large folios support Daniel Gomez
[not found] ` <CGME20240515055724eucas1p1c502dbded4dc6ff929c7aff570de80c2@eucas1p1.samsung.com>
2024-05-15 5:57 ` [PATCH 01/12] splice: don't check for uptodate if partially uptodate is impl Daniel Gomez
[not found] ` <CGME20240515055726eucas1p2a795fc743373571bfc3349f9e1ef3f9e@eucas1p2.samsung.com>
2024-05-15 5:57 ` [PATCH 02/12] shmem: add per-block uptodate tracking for large folios Daniel Gomez
[not found] ` <CGME20240515055727eucas1p2413c65b8b227ac0c6007b4600574abd8@eucas1p2.samsung.com>
2024-05-15 5:57 ` [PATCH 03/12] shmem: move folio zero operation to write_begin() Daniel Gomez
[not found] ` <CGME20240515055728eucas1p181e0ed81b2663eb0eee6d6134c1c1956@eucas1p1.samsung.com>
2024-05-15 5:57 ` [PATCH 04/12] shmem: exit shmem_get_folio_gfp() if block is uptodate Daniel Gomez
[not found] ` <CGME20240515055729eucas1p14e953424ad39bbb923c64163b1bbd4b3@eucas1p1.samsung.com>
2024-05-15 5:57 ` [PATCH 05/12] shmem: clear_highpage() if block is not uptodate Daniel Gomez
[not found] ` <CGME20240515055731eucas1p12cbbba88e24a011ef5871f90ff25ae73@eucas1p1.samsung.com>
2024-05-15 5:57 ` [PATCH 06/12] shmem: set folio uptodate when reclaim Daniel Gomez
[not found] ` <CGME20240515055732eucas1p2302bbca4d60e2e811a5c59e34f83628d@eucas1p2.samsung.com>
2024-05-15 5:57 ` [PATCH 07/12] shmem: check if a block is uptodate before splice into pipe Daniel Gomez
2024-05-16 13:19 ` kernel test robot
[not found] ` <CGME20240515055733eucas1p2804d2fb5f5bf7d6adb460054f6e9f4d8@eucas1p2.samsung.com>
2024-05-15 5:57 ` [PATCH 08/12] shmem: clear uptodate blocks after PUNCH_HOLE Daniel Gomez
[not found] ` <CGME20240515055735eucas1p2a967b4eebc8e059588cd62139f006b0d@eucas1p2.samsung.com>
2024-05-15 5:57 ` [PATCH 09/12] shmem: enable per-block uptodate Daniel Gomez
[not found] ` <CGME20240515055736eucas1p1bfa9549398e766532d143ba9314bee18@eucas1p1.samsung.com>
2024-05-15 5:57 ` [PATCH 10/12] shmem: add order arg to shmem_alloc_folio() Daniel Gomez
[not found] ` <CGME20240515055738eucas1p15335a32c790b731aa5857193bbddf92d@eucas1p1.samsung.com>
2024-05-15 5:57 ` [PATCH 11/12] shmem: add file length arg in shmem_get_folio() path Daniel Gomez
2024-05-15 17:47 ` kernel test robot
2024-05-17 16:17 ` Darrick J. Wong
2024-05-21 11:38 ` Daniel Gomez
2024-05-21 16:36 ` Darrick J. Wong
[not found] ` <CGME20240515055740eucas1p1bf112e73a7009a0f9b2bbf09c989a51b@eucas1p1.samsung.com>
2024-05-15 5:57 ` [PATCH 12/12] shmem: add large folio support to the write and fallocate paths Daniel Gomez
2024-05-15 18:59 ` kernel test robot
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).