All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Matthew Wilcox (Oracle)" <willy@infradead.org>
To: Christoph Hellwig <hch@infradead.org>,
	"Darrick J . Wong" <djwong@kernel.org>
Cc: "Matthew Wilcox (Oracle)" <willy@infradead.org>,
	linux-xfs@vger.kernel.org, linux-fsdevel@vger.kernel.org,
	Andreas Gruenbacher <agruenba@redhat.com>,
	Gao Xiang <xiang@kernel.org>
Subject: [PATCH 1/2] filemap: Add folio_copy_tail()
Date: Fri,  3 Mar 2023 06:43:14 +0000	[thread overview]
Message-ID: <20230303064315.701090-2-willy@infradead.org> (raw)
In-Reply-To: <20230303064315.701090-1-willy@infradead.org>

This is a helper function for filesystems which support file tails.

Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
---
 include/linux/pagemap.h |  1 +
 mm/filemap.c            | 57 ++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 58 insertions(+)

diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h
index c21b3ad1068c..618fe184c248 100644
--- a/include/linux/pagemap.h
+++ b/include/linux/pagemap.h
@@ -764,6 +764,7 @@ static inline struct page *grab_cache_page(struct address_space *mapping,
 	return find_or_create_page(mapping, index, mapping_gfp_mask(mapping));
 }
 
+void folio_copy_tail(struct folio *, loff_t pos, void *src, size_t max);
 struct folio *read_cache_folio(struct address_space *, pgoff_t index,
 		filler_t *filler, struct file *file);
 struct folio *mapping_read_folio_gfp(struct address_space *, pgoff_t index,
diff --git a/mm/filemap.c b/mm/filemap.c
index 40be33b5ee46..b02d9c390d3c 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -4145,3 +4145,60 @@ bool filemap_release_folio(struct folio *folio, gfp_t gfp)
 	return try_to_free_buffers(folio);
 }
 EXPORT_SYMBOL(filemap_release_folio);
+
+/**
+ * folio_copy_tail - Copy an in-memory file tail into a page cache folio.
+ * @folio: The folio to copy into.
+ * @pos: The file position of the first byte of data in the tail.
+ * @src: The address of the tail data.
+ * @max: The size of the buffer used for the tail data.
+ *
+ * Supports file tails starting at @pos that are a maximum of @max
+ * bytes in size.  Zeroes the remainder of the folio.
+ */
+void folio_copy_tail(struct folio *folio, loff_t pos, void *src, size_t max)
+{
+	loff_t isize = i_size_read(folio->mapping->host);
+	size_t offset, len = isize - pos;
+	char *dst;
+
+	if (folio_pos(folio) > isize) {
+		len = 0;
+	} else if (folio_pos(folio) > pos) {
+		len -= folio_pos(folio) - pos;
+		src += folio_pos(folio) - pos;
+		max -= folio_pos(folio) - pos;
+		pos = folio_pos(folio);
+	}
+	/*
+	 * i_size is larger than the number of bytes stored in the tail?
+	 * Assume the remainder is zero-padded.
+	 */
+	if (WARN_ON_ONCE(len > max))
+		len = max;
+	offset = offset_in_folio(folio, pos);
+	dst = kmap_local_folio(folio, offset);
+	if (folio_test_highmem(folio) && folio_test_large(folio)) {
+		size_t poff = offset_in_page(offset);
+		size_t plen = min(poff + len, PAGE_SIZE) - poff;
+
+		for (;;) {
+			memcpy(dst, src, plen);
+			memset(dst + plen, 0, PAGE_SIZE - poff - plen);
+			offset += PAGE_SIZE - poff;
+			if (offset == folio_size(folio))
+				break;
+			kunmap_local(dst);
+			dst = kmap_local_folio(folio, offset);
+			len -= plen;
+			poff = 0;
+			plen = min(len, PAGE_SIZE);
+		}
+	} else {
+		memcpy(dst, src, len);
+		memset(dst + len, 0, folio_size(folio) - len - offset);
+	}
+	kunmap_local(dst);
+	flush_dcache_folio(folio);
+}
+EXPORT_SYMBOL_GPL(folio_copy_tail);
-- 
2.39.1


  reply	other threads:[~2023-03-03  6:43 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-03-03  6:43 [PATCH 0/2] folio_copy_tail Matthew Wilcox (Oracle)
2023-03-03  6:43 ` Matthew Wilcox (Oracle) [this message]
2023-03-03  9:53   ` [lkp] [+165 bytes kernel size regression] [i386-tinyconfig] [a4ee841f30] filemap: Add folio_copy_tail() kernel test robot
2023-03-03 12:05   ` [PATCH 1/2] " kernel test robot
2023-03-03  6:43 ` [PATCH 2/2] iomap: Use folio_copy_tail() Matthew Wilcox (Oracle)

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20230303064315.701090-2-willy@infradead.org \
    --to=willy@infradead.org \
    --cc=agruenba@redhat.com \
    --cc=djwong@kernel.org \
    --cc=hch@infradead.org \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-xfs@vger.kernel.org \
    --cc=xiang@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.