* [PATCH] btrfs: migrate to use folio private instead of page private
@ 2023-11-17 3:54 Qu Wenruo
2023-11-17 19:08 ` Josef Bacik
` (3 more replies)
0 siblings, 4 replies; 5+ messages in thread
From: Qu Wenruo @ 2023-11-17 3:54 UTC (permalink / raw)
To: linux-btrfs
As a cleanup and preparation for future folio migration, this patch
would replace all page->private to folio version.
This includes:
- PagePrivate()
-> folio_test_private()
- page->private
-> folio_get_private()
- attach_page_private()
-> folio_attach_private()
- detach_page_private()
-> folio_detach_private()
Since we're here, also remove the forced cast on page->private, since
it's (void *) already, we don't really need to do the cast.
For now even if we missed some call sites, it won't cause any problem
yet, as we're only using order 0 folio (single page), thus all those
folio/page flags should be synced.
But for the future conversion to utilize higher order folio, the page
<-> folio flag sync is no longer guaranteed, thus we have to migrate to
utilize folio flags.
Signed-off-by: Qu Wenruo <wqu@suse.com>
---
Just to mention, I really like the new unified folio flag accessors, no
more weird camel case.
---
fs/btrfs/extent_io.c | 98 +++++++++++++++++++++++++-------------------
fs/btrfs/extent_io.h | 6 +--
fs/btrfs/file.c | 5 ++-
fs/btrfs/inode.c | 7 ++--
fs/btrfs/subpage.c | 92 ++++++++++++++++++++++++++---------------
5 files changed, 124 insertions(+), 84 deletions(-)
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
index 004b0ba6b1c7..99cc16aed9d7 100644
--- a/fs/btrfs/extent_io.c
+++ b/fs/btrfs/extent_io.c
@@ -562,11 +562,13 @@ static void endio_readpage_release_extent(struct processed_extent *processed,
static void begin_page_read(struct btrfs_fs_info *fs_info, struct page *page)
{
+ struct folio *folio = page_folio(page);
+
ASSERT(PageLocked(page));
if (!btrfs_is_subpage(fs_info, page))
return;
- ASSERT(PagePrivate(page));
+ ASSERT(folio_test_private(folio));
btrfs_subpage_start_reader(fs_info, page, page_offset(page), PAGE_SIZE);
}
@@ -860,6 +862,7 @@ static int attach_extent_buffer_page(struct extent_buffer *eb,
struct page *page,
struct btrfs_subpage *prealloc)
{
+ struct folio *folio = page_folio(page);
struct btrfs_fs_info *fs_info = eb->fs_info;
int ret = 0;
@@ -873,22 +876,22 @@ static int attach_extent_buffer_page(struct extent_buffer *eb,
lockdep_assert_held(&page->mapping->private_lock);
if (fs_info->nodesize >= PAGE_SIZE) {
- if (!PagePrivate(page))
- attach_page_private(page, eb);
+ if (!folio_test_private(folio))
+ folio_attach_private(folio, eb);
else
- WARN_ON(page->private != (unsigned long)eb);
+ WARN_ON(folio_get_private(folio) != eb);
return 0;
}
/* Already mapped, just free prealloc */
- if (PagePrivate(page)) {
+ if (folio_test_private(folio)) {
btrfs_free_subpage(prealloc);
return 0;
}
if (prealloc)
/* Has preallocated memory for subpage */
- attach_page_private(page, prealloc);
+ folio_attach_private(folio, prealloc);
else
/* Do new allocation to attach subpage */
ret = btrfs_attach_subpage(fs_info, page,
@@ -898,11 +901,12 @@ static int attach_extent_buffer_page(struct extent_buffer *eb,
int set_page_extent_mapped(struct page *page)
{
+ struct folio *folio = page_folio(page);
struct btrfs_fs_info *fs_info;
ASSERT(page->mapping);
- if (PagePrivate(page))
+ if (folio_test_private(folio))
return 0;
fs_info = btrfs_sb(page->mapping->host->i_sb);
@@ -910,24 +914,25 @@ int set_page_extent_mapped(struct page *page)
if (btrfs_is_subpage(fs_info, page))
return btrfs_attach_subpage(fs_info, page, BTRFS_SUBPAGE_DATA);
- attach_page_private(page, (void *)EXTENT_PAGE_PRIVATE);
+ folio_attach_private(folio, (void *)EXTENT_FOLIO_PRIVATE);
return 0;
}
void clear_page_extent_mapped(struct page *page)
{
+ struct folio *folio = page_folio(page);
struct btrfs_fs_info *fs_info;
ASSERT(page->mapping);
- if (!PagePrivate(page))
+ if (!folio_test_private(folio))
return;
fs_info = btrfs_sb(page->mapping->host->i_sb);
if (btrfs_is_subpage(fs_info, page))
return btrfs_detach_subpage(fs_info, page);
- detach_page_private(page);
+ folio_detach_private(folio);
}
static struct extent_map *
@@ -1235,7 +1240,8 @@ static noinline_for_stack int writepage_delalloc(struct btrfs_inode *inode,
static void find_next_dirty_byte(struct btrfs_fs_info *fs_info,
struct page *page, u64 *start, u64 *end)
{
- struct btrfs_subpage *subpage = (struct btrfs_subpage *)page->private;
+ struct folio *folio = page_folio(page);
+ struct btrfs_subpage *subpage = folio_get_private(folio);
struct btrfs_subpage_info *spi = fs_info->subpage_info;
u64 orig_start = *start;
/* Declare as unsigned long so we can use bitmap ops */
@@ -1720,6 +1726,7 @@ static noinline_for_stack void write_one_eb(struct extent_buffer *eb,
static int submit_eb_subpage(struct page *page, struct writeback_control *wbc)
{
struct btrfs_fs_info *fs_info = btrfs_sb(page->mapping->host->i_sb);
+ struct folio *folio = page_folio(page);
int submitted = 0;
u64 page_start = page_offset(page);
int bit_start = 0;
@@ -1727,7 +1734,7 @@ static int submit_eb_subpage(struct page *page, struct writeback_control *wbc)
/* Lock and write each dirty extent buffers in the range */
while (bit_start < fs_info->subpage_info->bitmap_nr_bits) {
- struct btrfs_subpage *subpage = (struct btrfs_subpage *)page->private;
+ struct btrfs_subpage *subpage = folio_get_private(folio);
struct extent_buffer *eb;
unsigned long flags;
u64 start;
@@ -1737,7 +1744,7 @@ static int submit_eb_subpage(struct page *page, struct writeback_control *wbc)
* in the meantime.
*/
spin_lock(&page->mapping->private_lock);
- if (!PagePrivate(page)) {
+ if (!folio_test_private(folio)) {
spin_unlock(&page->mapping->private_lock);
break;
}
@@ -1802,22 +1809,23 @@ static int submit_eb_page(struct page *page, struct btrfs_eb_write_context *ctx)
{
struct writeback_control *wbc = ctx->wbc;
struct address_space *mapping = page->mapping;
+ struct folio *folio = page_folio(page);
struct extent_buffer *eb;
int ret;
- if (!PagePrivate(page))
+ if (!folio_test_private(folio))
return 0;
if (btrfs_sb(page->mapping->host->i_sb)->nodesize < PAGE_SIZE)
return submit_eb_subpage(page, wbc);
spin_lock(&mapping->private_lock);
- if (!PagePrivate(page)) {
+ if (!folio_test_private(folio)) {
spin_unlock(&mapping->private_lock);
return 0;
}
- eb = (struct extent_buffer *)page->private;
+ eb = folio_get_private(folio);
/*
* Shouldn't happen and normally this would be a BUG_ON but no point
@@ -3054,12 +3062,13 @@ static int extent_buffer_under_io(const struct extent_buffer *eb)
static bool page_range_has_eb(struct btrfs_fs_info *fs_info, struct page *page)
{
+ struct folio *folio = page_folio(page);
struct btrfs_subpage *subpage;
lockdep_assert_held(&page->mapping->private_lock);
- if (PagePrivate(page)) {
- subpage = (struct btrfs_subpage *)page->private;
+ if (folio_test_private(folio)) {
+ subpage = folio_get_private(folio);
if (atomic_read(&subpage->eb_refs))
return true;
/*
@@ -3076,15 +3085,16 @@ static void detach_extent_buffer_page(struct extent_buffer *eb, struct page *pag
{
struct btrfs_fs_info *fs_info = eb->fs_info;
const bool mapped = !test_bit(EXTENT_BUFFER_UNMAPPED, &eb->bflags);
+ struct folio *folio = page_folio(page);
/*
- * For mapped eb, we're going to change the page private, which should
+ * For mapped eb, we're going to change the folio private, which should
* be done under the private_lock.
*/
if (mapped)
spin_lock(&page->mapping->private_lock);
- if (!PagePrivate(page)) {
+ if (!folio_test_private(folio)) {
if (mapped)
spin_unlock(&page->mapping->private_lock);
return;
@@ -3095,11 +3105,11 @@ static void detach_extent_buffer_page(struct extent_buffer *eb, struct page *pag
* We do this since we'll remove the pages after we've
* removed the eb from the radix tree, so we could race
* and have this page now attached to the new eb. So
- * only clear page_private if it's still connected to
+ * only clear folio if it's still connected to
* this eb.
*/
- if (PagePrivate(page) &&
- page->private == (unsigned long)eb) {
+ if (folio_test_private(folio) &&
+ folio_get_private(folio) == eb) {
BUG_ON(test_bit(EXTENT_BUFFER_DIRTY, &eb->bflags));
BUG_ON(PageDirty(page));
BUG_ON(PageWriteback(page));
@@ -3107,7 +3117,7 @@ static void detach_extent_buffer_page(struct extent_buffer *eb, struct page *pag
* We need to make sure we haven't be attached
* to a new eb.
*/
- detach_page_private(page);
+ folio_detach_private(folio);
}
if (mapped)
spin_unlock(&page->mapping->private_lock);
@@ -3115,9 +3125,9 @@ static void detach_extent_buffer_page(struct extent_buffer *eb, struct page *pag
}
/*
- * For subpage, we can have dummy eb with page private. In this case,
- * we can directly detach the private as such page is only attached to
- * one dummy eb, no sharing.
+ * For subpage, we can have dummy eb with folio private attached.
+ * In this case, we can directly detach the private as such folio is
+ * only attached to one dummy eb, no sharing.
*/
if (!mapped) {
btrfs_detach_subpage(fs_info, page);
@@ -3127,7 +3137,7 @@ static void detach_extent_buffer_page(struct extent_buffer *eb, struct page *pag
btrfs_page_dec_eb_refs(fs_info, page);
/*
- * We can only detach the page private if there are no other ebs in the
+ * We can only detach the folio private if there are no other ebs in the
* page range and no unfinished IO.
*/
if (!page_range_has_eb(fs_info, page))
@@ -3404,6 +3414,7 @@ struct extent_buffer *alloc_test_extent_buffer(struct btrfs_fs_info *fs_info,
static struct extent_buffer *grab_extent_buffer(
struct btrfs_fs_info *fs_info, struct page *page)
{
+ struct folio *folio = page_folio(page);
struct extent_buffer *exists;
/*
@@ -3415,21 +3426,21 @@ static struct extent_buffer *grab_extent_buffer(
return NULL;
/* Page not yet attached to an extent buffer */
- if (!PagePrivate(page))
+ if (!folio_test_private(folio))
return NULL;
/*
* We could have already allocated an eb for this page and attached one
* so lets see if we can get a ref on the existing eb, and if we can we
* know it's good and we can just return that one, else we know we can
- * just overwrite page->private.
+ * just overwrite folio private.
*/
- exists = (struct extent_buffer *)page->private;
+ exists = folio_get_private(folio);
if (atomic_inc_not_zero(&exists->refs))
return exists;
WARN_ON(PageDirty(page));
- detach_page_private(page);
+ folio_detach_private(folio);
return NULL;
}
@@ -3514,7 +3525,7 @@ struct extent_buffer *alloc_extent_buffer(struct btrfs_fs_info *fs_info,
num_pages = num_extent_pages(eb);
/*
- * Preallocate page->private for subpage case, so that we won't
+ * Preallocate folio private for subpage case, so that we won't
* allocate memory with private_lock nor page lock hold.
*
* The memory will be freed by attach_extent_buffer_page() or freed
@@ -3551,7 +3562,7 @@ struct extent_buffer *alloc_extent_buffer(struct btrfs_fs_info *fs_info,
ASSERT(!ret);
/*
* To inform we have extra eb under allocation, so that
- * detach_extent_buffer_page() won't release the page private
+ * detach_extent_buffer_page() won't release the folio private
* when the eb hasn't yet been inserted into radix tree.
*
* The ref will be decreased when the eb released the page, in
@@ -4569,7 +4580,7 @@ static int try_release_subpage_extent_buffer(struct page *page)
struct extent_buffer *eb = NULL;
/*
- * Unlike try_release_extent_buffer() which uses page->private
+ * Unlike try_release_extent_buffer() which uses folio private
* to grab buffer, for subpage case we rely on radix tree, thus
* we need to ensure radix tree consistency.
*
@@ -4609,17 +4620,17 @@ static int try_release_subpage_extent_buffer(struct page *page)
/*
* Here we don't care about the return value, we will always
- * check the page private at the end. And
+ * check the folio private at the end. And
* release_extent_buffer() will release the refs_lock.
*/
release_extent_buffer(eb);
}
/*
- * Finally to check if we have cleared page private, as if we have
- * released all ebs in the page, the page private should be cleared now.
+ * Finally to check if we have cleared folio private, as if we have
+ * released all ebs in the page, the folio private should be cleared now.
*/
spin_lock(&page->mapping->private_lock);
- if (!PagePrivate(page))
+ if (!folio_test_private(page_folio(page)))
ret = 1;
else
ret = 0;
@@ -4630,22 +4641,23 @@ static int try_release_subpage_extent_buffer(struct page *page)
int try_release_extent_buffer(struct page *page)
{
+ struct folio *folio = page_folio(page);
struct extent_buffer *eb;
if (btrfs_sb(page->mapping->host->i_sb)->nodesize < PAGE_SIZE)
return try_release_subpage_extent_buffer(page);
/*
- * We need to make sure nobody is changing page->private, as we rely on
- * page->private as the pointer to extent buffer.
+ * We need to make sure nobody is changing folio private, as we rely on
+ * folio private as the pointer to extent buffer.
*/
spin_lock(&page->mapping->private_lock);
- if (!PagePrivate(page)) {
+ if (!folio_test_private(folio)) {
spin_unlock(&page->mapping->private_lock);
return 1;
}
- eb = (struct extent_buffer *)page->private;
+ eb = folio_get_private(folio);
BUG_ON(!eb);
/*
diff --git a/fs/btrfs/extent_io.h b/fs/btrfs/extent_io.h
index a88374ad248f..6531285ef0bc 100644
--- a/fs/btrfs/extent_io.h
+++ b/fs/btrfs/extent_io.h
@@ -43,10 +43,10 @@ enum {
};
/*
- * page->private values. Every page that is controlled by the extent
- * map has page->private set to one.
+ * folio private values. Every page that is controlled by the extent
+ * map has folio private set to this value.
*/
-#define EXTENT_PAGE_PRIVATE 1
+#define EXTENT_FOLIO_PRIVATE 1
/*
* The extent buffer bitmap operations are done with byte granularity instead of
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
index f47731c45bb5..6197f585cdff 100644
--- a/fs/btrfs/file.c
+++ b/fs/btrfs/file.c
@@ -869,9 +869,10 @@ static int prepare_uptodate_page(struct inode *inode,
* released.
*
* The private flag check is essential for subpage as we need
- * to store extra bitmap using page->private.
+ * to store extra bitmap using folio private.
*/
- if (page->mapping != inode->i_mapping || !PagePrivate(page)) {
+ if (page->mapping != inode->i_mapping ||
+ !folio_test_private(folio)) {
unlock_page(page);
return -EAGAIN;
}
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 9f5a9894f88f..40f64322b1f1 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -4725,7 +4725,7 @@ int btrfs_truncate_block(struct btrfs_inode *inode, loff_t from, loff_t len,
/*
* We unlock the page after the io is completed and then re-lock it
* above. release_folio() could have come in between that and cleared
- * PagePrivate(), but left the page in the mapping. Set the page mapped
+ * folio private, but left the page in the mapping. Set the page mapped
* here to make sure it's properly set for the subpage stuff.
*/
ret = set_page_extent_mapped(page);
@@ -7851,13 +7851,14 @@ static void btrfs_readahead(struct readahead_control *rac)
static void wait_subpage_spinlock(struct page *page)
{
struct btrfs_fs_info *fs_info = btrfs_sb(page->mapping->host->i_sb);
+ struct folio *folio = page_folio(page);
struct btrfs_subpage *subpage;
if (!btrfs_is_subpage(fs_info, page))
return;
- ASSERT(PagePrivate(page) && page->private);
- subpage = (struct btrfs_subpage *)page->private;
+ ASSERT(folio_test_private(folio) && folio_get_private(folio));
+ subpage = folio_get_private(folio);
/*
* This may look insane as we just acquire the spinlock and release it,
diff --git a/fs/btrfs/subpage.c b/fs/btrfs/subpage.c
index 1b999c6e4193..72d8dd516db9 100644
--- a/fs/btrfs/subpage.c
+++ b/fs/btrfs/subpage.c
@@ -118,6 +118,7 @@ void btrfs_init_subpage_info(struct btrfs_subpage_info *subpage_info, u32 sector
int btrfs_attach_subpage(const struct btrfs_fs_info *fs_info,
struct page *page, enum btrfs_subpage_type type)
{
+ struct folio *folio = page_folio(page);
struct btrfs_subpage *subpage;
/*
@@ -127,28 +128,29 @@ int btrfs_attach_subpage(const struct btrfs_fs_info *fs_info,
if (page->mapping)
ASSERT(PageLocked(page));
- /* Either not subpage, or the page already has private attached */
- if (!btrfs_is_subpage(fs_info, page) || PagePrivate(page))
+ /* Either not subpage, or the folio already has private attached */
+ if (!btrfs_is_subpage(fs_info, page) || folio_test_private(folio))
return 0;
subpage = btrfs_alloc_subpage(fs_info, type);
if (IS_ERR(subpage))
return PTR_ERR(subpage);
- attach_page_private(page, subpage);
+ folio_attach_private(folio, subpage);
return 0;
}
void btrfs_detach_subpage(const struct btrfs_fs_info *fs_info,
struct page *page)
{
+ struct folio *folio = page_folio(page);
struct btrfs_subpage *subpage;
/* Either not subpage, or already detached */
- if (!btrfs_is_subpage(fs_info, page) || !PagePrivate(page))
+ if (!btrfs_is_subpage(fs_info, page) || !folio_test_private(folio))
return;
- subpage = detach_page_private(page);
+ subpage = folio_detach_private(folio);
ASSERT(subpage);
btrfs_free_subpage(subpage);
}
@@ -188,36 +190,38 @@ void btrfs_free_subpage(struct btrfs_subpage *subpage)
* This is important for eb allocation, to prevent race with last eb freeing
* of the same page.
* With the eb_refs increased before the eb inserted into radix tree,
- * detach_extent_buffer_page() won't detach the page private while we're still
+ * detach_extent_buffer_page() won't detach the folio private while we're still
* allocating the extent buffer.
*/
void btrfs_page_inc_eb_refs(const struct btrfs_fs_info *fs_info,
struct page *page)
{
+ struct folio *folio = page_folio(page);
struct btrfs_subpage *subpage;
if (!btrfs_is_subpage(fs_info, page))
return;
- ASSERT(PagePrivate(page) && page->mapping);
+ ASSERT(folio_test_private(folio) && page->mapping);
lockdep_assert_held(&page->mapping->private_lock);
- subpage = (struct btrfs_subpage *)page->private;
+ subpage = folio_get_private(folio);
atomic_inc(&subpage->eb_refs);
}
void btrfs_page_dec_eb_refs(const struct btrfs_fs_info *fs_info,
struct page *page)
{
+ struct folio *folio = page_folio(page);
struct btrfs_subpage *subpage;
if (!btrfs_is_subpage(fs_info, page))
return;
- ASSERT(PagePrivate(page) && page->mapping);
+ ASSERT(folio_test_private(folio) && page->mapping);
lockdep_assert_held(&page->mapping->private_lock);
- subpage = (struct btrfs_subpage *)page->private;
+ subpage = folio_get_private(folio);
ASSERT(atomic_read(&subpage->eb_refs));
atomic_dec(&subpage->eb_refs);
}
@@ -225,8 +229,10 @@ void btrfs_page_dec_eb_refs(const struct btrfs_fs_info *fs_info,
static void btrfs_subpage_assert(const struct btrfs_fs_info *fs_info,
struct page *page, u64 start, u32 len)
{
+ struct folio *folio = page_folio(page);
+
/* Basic checks */
- ASSERT(PagePrivate(page) && page->private);
+ ASSERT(folio_test_private(folio) && folio_get_private(folio));
ASSERT(IS_ALIGNED(start, fs_info->sectorsize) &&
IS_ALIGNED(len, fs_info->sectorsize));
/*
@@ -241,7 +247,8 @@ static void btrfs_subpage_assert(const struct btrfs_fs_info *fs_info,
void btrfs_subpage_start_reader(const struct btrfs_fs_info *fs_info,
struct page *page, u64 start, u32 len)
{
- struct btrfs_subpage *subpage = (struct btrfs_subpage *)page->private;
+ struct folio *folio = page_folio(page);
+ struct btrfs_subpage *subpage = folio_get_private(folio);
const int nbits = len >> fs_info->sectorsize_bits;
btrfs_subpage_assert(fs_info, page, start, len);
@@ -252,7 +259,8 @@ void btrfs_subpage_start_reader(const struct btrfs_fs_info *fs_info,
void btrfs_subpage_end_reader(const struct btrfs_fs_info *fs_info,
struct page *page, u64 start, u32 len)
{
- struct btrfs_subpage *subpage = (struct btrfs_subpage *)page->private;
+ struct folio *folio = page_folio(page);
+ struct btrfs_subpage *subpage = folio_get_private(folio);
const int nbits = len >> fs_info->sectorsize_bits;
bool is_data;
bool last;
@@ -294,7 +302,8 @@ static void btrfs_subpage_clamp_range(struct page *page, u64 *start, u32 *len)
void btrfs_subpage_start_writer(const struct btrfs_fs_info *fs_info,
struct page *page, u64 start, u32 len)
{
- struct btrfs_subpage *subpage = (struct btrfs_subpage *)page->private;
+ struct folio *folio = page_folio(page);
+ struct btrfs_subpage *subpage = folio_get_private(folio);
const int nbits = (len >> fs_info->sectorsize_bits);
int ret;
@@ -308,7 +317,8 @@ void btrfs_subpage_start_writer(const struct btrfs_fs_info *fs_info,
bool btrfs_subpage_end_and_test_writer(const struct btrfs_fs_info *fs_info,
struct page *page, u64 start, u32 len)
{
- struct btrfs_subpage *subpage = (struct btrfs_subpage *)page->private;
+ struct folio *folio = page_folio(page);
+ struct btrfs_subpage *subpage = folio_get_private(folio);
const int nbits = (len >> fs_info->sectorsize_bits);
btrfs_subpage_assert(fs_info, page, start, len);
@@ -340,12 +350,14 @@ bool btrfs_subpage_end_and_test_writer(const struct btrfs_fs_info *fs_info,
int btrfs_page_start_writer_lock(const struct btrfs_fs_info *fs_info,
struct page *page, u64 start, u32 len)
{
+ struct folio *folio = page_folio(page);
+
if (unlikely(!fs_info) || !btrfs_is_subpage(fs_info, page)) {
lock_page(page);
return 0;
}
lock_page(page);
- if (!PagePrivate(page) || !page->private) {
+ if (!folio_test_private(folio) || !folio_get_private(folio)) {
unlock_page(page);
return -EAGAIN;
}
@@ -387,7 +399,8 @@ void btrfs_page_end_writer_lock(const struct btrfs_fs_info *fs_info,
void btrfs_subpage_set_uptodate(const struct btrfs_fs_info *fs_info,
struct page *page, u64 start, u32 len)
{
- struct btrfs_subpage *subpage = (struct btrfs_subpage *)page->private;
+ struct folio *folio = page_folio(page);
+ struct btrfs_subpage *subpage = folio_get_private(folio);
unsigned int start_bit = subpage_calc_start_bit(fs_info, page,
uptodate, start, len);
unsigned long flags;
@@ -402,7 +415,8 @@ void btrfs_subpage_set_uptodate(const struct btrfs_fs_info *fs_info,
void btrfs_subpage_clear_uptodate(const struct btrfs_fs_info *fs_info,
struct page *page, u64 start, u32 len)
{
- struct btrfs_subpage *subpage = (struct btrfs_subpage *)page->private;
+ struct folio *folio = page_folio(page);
+ struct btrfs_subpage *subpage = folio_get_private(folio);
unsigned int start_bit = subpage_calc_start_bit(fs_info, page,
uptodate, start, len);
unsigned long flags;
@@ -416,7 +430,8 @@ void btrfs_subpage_clear_uptodate(const struct btrfs_fs_info *fs_info,
void btrfs_subpage_set_dirty(const struct btrfs_fs_info *fs_info,
struct page *page, u64 start, u32 len)
{
- struct btrfs_subpage *subpage = (struct btrfs_subpage *)page->private;
+ struct folio *folio = page_folio(page);
+ struct btrfs_subpage *subpage = folio_get_private(folio);
unsigned int start_bit = subpage_calc_start_bit(fs_info, page,
dirty, start, len);
unsigned long flags;
@@ -440,7 +455,8 @@ void btrfs_subpage_set_dirty(const struct btrfs_fs_info *fs_info,
bool btrfs_subpage_clear_and_test_dirty(const struct btrfs_fs_info *fs_info,
struct page *page, u64 start, u32 len)
{
- struct btrfs_subpage *subpage = (struct btrfs_subpage *)page->private;
+ struct folio *folio = page_folio(page);
+ struct btrfs_subpage *subpage = folio_get_private(folio);
unsigned int start_bit = subpage_calc_start_bit(fs_info, page,
dirty, start, len);
unsigned long flags;
@@ -467,7 +483,8 @@ void btrfs_subpage_clear_dirty(const struct btrfs_fs_info *fs_info,
void btrfs_subpage_set_writeback(const struct btrfs_fs_info *fs_info,
struct page *page, u64 start, u32 len)
{
- struct btrfs_subpage *subpage = (struct btrfs_subpage *)page->private;
+ struct folio *folio = page_folio(page);
+ struct btrfs_subpage *subpage = folio_get_private(folio);
unsigned int start_bit = subpage_calc_start_bit(fs_info, page,
writeback, start, len);
unsigned long flags;
@@ -481,7 +498,8 @@ void btrfs_subpage_set_writeback(const struct btrfs_fs_info *fs_info,
void btrfs_subpage_clear_writeback(const struct btrfs_fs_info *fs_info,
struct page *page, u64 start, u32 len)
{
- struct btrfs_subpage *subpage = (struct btrfs_subpage *)page->private;
+ struct folio *folio = page_folio(page);
+ struct btrfs_subpage *subpage = folio_get_private(folio);
unsigned int start_bit = subpage_calc_start_bit(fs_info, page,
writeback, start, len);
unsigned long flags;
@@ -498,7 +516,8 @@ void btrfs_subpage_clear_writeback(const struct btrfs_fs_info *fs_info,
void btrfs_subpage_set_ordered(const struct btrfs_fs_info *fs_info,
struct page *page, u64 start, u32 len)
{
- struct btrfs_subpage *subpage = (struct btrfs_subpage *)page->private;
+ struct folio *folio = page_folio(page);
+ struct btrfs_subpage *subpage = folio_get_private(folio);
unsigned int start_bit = subpage_calc_start_bit(fs_info, page,
ordered, start, len);
unsigned long flags;
@@ -512,7 +531,8 @@ void btrfs_subpage_set_ordered(const struct btrfs_fs_info *fs_info,
void btrfs_subpage_clear_ordered(const struct btrfs_fs_info *fs_info,
struct page *page, u64 start, u32 len)
{
- struct btrfs_subpage *subpage = (struct btrfs_subpage *)page->private;
+ struct folio *folio = page_folio(page);
+ struct btrfs_subpage *subpage = folio_get_private(folio);
unsigned int start_bit = subpage_calc_start_bit(fs_info, page,
ordered, start, len);
unsigned long flags;
@@ -527,7 +547,8 @@ void btrfs_subpage_clear_ordered(const struct btrfs_fs_info *fs_info,
void btrfs_subpage_set_checked(const struct btrfs_fs_info *fs_info,
struct page *page, u64 start, u32 len)
{
- struct btrfs_subpage *subpage = (struct btrfs_subpage *)page->private;
+ struct folio *folio = page_folio(page);
+ struct btrfs_subpage *subpage = folio_get_private(folio);
unsigned int start_bit = subpage_calc_start_bit(fs_info, page,
checked, start, len);
unsigned long flags;
@@ -542,7 +563,8 @@ void btrfs_subpage_set_checked(const struct btrfs_fs_info *fs_info,
void btrfs_subpage_clear_checked(const struct btrfs_fs_info *fs_info,
struct page *page, u64 start, u32 len)
{
- struct btrfs_subpage *subpage = (struct btrfs_subpage *)page->private;
+ struct folio *folio = page_folio(page);
+ struct btrfs_subpage *subpage = folio_get_private(folio);
unsigned int start_bit = subpage_calc_start_bit(fs_info, page,
checked, start, len);
unsigned long flags;
@@ -561,7 +583,8 @@ void btrfs_subpage_clear_checked(const struct btrfs_fs_info *fs_info,
bool btrfs_subpage_test_##name(const struct btrfs_fs_info *fs_info, \
struct page *page, u64 start, u32 len) \
{ \
- struct btrfs_subpage *subpage = (struct btrfs_subpage *)page->private; \
+ struct folio *folio = page_folio(page); \
+ struct btrfs_subpage *subpage = folio_get_private(folio); \
unsigned int start_bit = subpage_calc_start_bit(fs_info, page, \
name, start, len); \
unsigned long flags; \
@@ -656,7 +679,8 @@ IMPLEMENT_BTRFS_PAGE_OPS(checked, SetPageChecked, ClearPageChecked, PageChecked)
void btrfs_page_assert_not_dirty(const struct btrfs_fs_info *fs_info,
struct page *page)
{
- struct btrfs_subpage *subpage = (struct btrfs_subpage *)page->private;
+ struct folio *folio = page_folio(page);
+ struct btrfs_subpage *subpage = folio_get_private(folio);
if (!IS_ENABLED(CONFIG_BTRFS_ASSERT))
return;
@@ -665,7 +689,7 @@ void btrfs_page_assert_not_dirty(const struct btrfs_fs_info *fs_info,
if (!btrfs_is_subpage(fs_info, page))
return;
- ASSERT(PagePrivate(page) && page->private);
+ ASSERT(folio_test_private(folio) && folio_get_private(folio));
ASSERT(subpage_test_bitmap_all_zero(fs_info, subpage, dirty));
}
@@ -687,6 +711,7 @@ void btrfs_page_assert_not_dirty(const struct btrfs_fs_info *fs_info,
void btrfs_page_unlock_writer(struct btrfs_fs_info *fs_info, struct page *page,
u64 start, u32 len)
{
+ struct folio *folio = page_folio(page);
struct btrfs_subpage *subpage;
ASSERT(PageLocked(page));
@@ -694,8 +719,8 @@ void btrfs_page_unlock_writer(struct btrfs_fs_info *fs_info, struct page *page,
if (!btrfs_is_subpage(fs_info, page))
return unlock_page(page);
- ASSERT(PagePrivate(page) && page->private);
- subpage = (struct btrfs_subpage *)page->private;
+ ASSERT(folio_test_private(folio) && folio_get_private(folio));
+ subpage = folio_get_private(folio);
/*
* For subpage case, there are two types of locked page. With or
@@ -720,6 +745,7 @@ void __cold btrfs_subpage_dump_bitmap(const struct btrfs_fs_info *fs_info,
struct page *page, u64 start, u32 len)
{
struct btrfs_subpage_info *subpage_info = fs_info->subpage_info;
+ struct folio *folio = page_folio(page);
struct btrfs_subpage *subpage;
unsigned long uptodate_bitmap;
unsigned long error_bitmap;
@@ -729,9 +755,9 @@ void __cold btrfs_subpage_dump_bitmap(const struct btrfs_fs_info *fs_info,
unsigned long checked_bitmap;
unsigned long flags;
- ASSERT(PagePrivate(page) && page->private);
+ ASSERT(folio_test_private(folio) && folio_get_private(folio));
ASSERT(subpage_info);
- subpage = (struct btrfs_subpage *)page->private;
+ subpage = folio_get_private(folio);
spin_lock_irqsave(&subpage->lock, flags);
GET_SUBPAGE_BITMAP(subpage, subpage_info, uptodate, &uptodate_bitmap);
--
2.42.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH] btrfs: migrate to use folio private instead of page private
2023-11-17 3:54 [PATCH] btrfs: migrate to use folio private instead of page private Qu Wenruo
@ 2023-11-17 19:08 ` Josef Bacik
2023-11-17 23:56 ` Neal Gompa
` (2 subsequent siblings)
3 siblings, 0 replies; 5+ messages in thread
From: Josef Bacik @ 2023-11-17 19:08 UTC (permalink / raw)
To: Qu Wenruo; +Cc: linux-btrfs
On Fri, Nov 17, 2023 at 02:24:14PM +1030, Qu Wenruo wrote:
> As a cleanup and preparation for future folio migration, this patch
> would replace all page->private to folio version.
> This includes:
>
> - PagePrivate()
> -> folio_test_private()
>
> - page->private
> -> folio_get_private()
>
> - attach_page_private()
> -> folio_attach_private()
>
> - detach_page_private()
> -> folio_detach_private()
>
> Since we're here, also remove the forced cast on page->private, since
> it's (void *) already, we don't really need to do the cast.
>
> For now even if we missed some call sites, it won't cause any problem
> yet, as we're only using order 0 folio (single page), thus all those
> folio/page flags should be synced.
>
> But for the future conversion to utilize higher order folio, the page
> <-> folio flag sync is no longer guaranteed, thus we have to migrate to
> utilize folio flags.
>
> Signed-off-by: Qu Wenruo <wqu@suse.com>
Reviewed-by: Josef Bacik <josef@toxicpanda.com>
Thanks,
Josef
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] btrfs: migrate to use folio private instead of page private
2023-11-17 3:54 [PATCH] btrfs: migrate to use folio private instead of page private Qu Wenruo
2023-11-17 19:08 ` Josef Bacik
@ 2023-11-17 23:56 ` Neal Gompa
2023-11-20 7:45 ` Johannes Thumshirn
2023-11-21 12:58 ` David Sterba
3 siblings, 0 replies; 5+ messages in thread
From: Neal Gompa @ 2023-11-17 23:56 UTC (permalink / raw)
To: Qu Wenruo; +Cc: linux-btrfs
On Thu, Nov 16, 2023 at 10:54 PM Qu Wenruo <wqu@suse.com> wrote:
>
> As a cleanup and preparation for future folio migration, this patch
> would replace all page->private to folio version.
> This includes:
>
> - PagePrivate()
> -> folio_test_private()
>
> - page->private
> -> folio_get_private()
>
> - attach_page_private()
> -> folio_attach_private()
>
> - detach_page_private()
> -> folio_detach_private()
>
> Since we're here, also remove the forced cast on page->private, since
> it's (void *) already, we don't really need to do the cast.
>
> For now even if we missed some call sites, it won't cause any problem
> yet, as we're only using order 0 folio (single page), thus all those
> folio/page flags should be synced.
>
> But for the future conversion to utilize higher order folio, the page
> <-> folio flag sync is no longer guaranteed, thus we have to migrate to
> utilize folio flags.
>
> Signed-off-by: Qu Wenruo <wqu@suse.com>
> ---
> Just to mention, I really like the new unified folio flag accessors, no
> more weird camel case.
> ---
> fs/btrfs/extent_io.c | 98 +++++++++++++++++++++++++-------------------
> fs/btrfs/extent_io.h | 6 +--
> fs/btrfs/file.c | 5 ++-
> fs/btrfs/inode.c | 7 ++--
> fs/btrfs/subpage.c | 92 ++++++++++++++++++++++++++---------------
> 5 files changed, 124 insertions(+), 84 deletions(-)
>
> diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
> index 004b0ba6b1c7..99cc16aed9d7 100644
> --- a/fs/btrfs/extent_io.c
> +++ b/fs/btrfs/extent_io.c
> @@ -562,11 +562,13 @@ static void endio_readpage_release_extent(struct processed_extent *processed,
>
> static void begin_page_read(struct btrfs_fs_info *fs_info, struct page *page)
> {
> + struct folio *folio = page_folio(page);
> +
> ASSERT(PageLocked(page));
> if (!btrfs_is_subpage(fs_info, page))
> return;
>
> - ASSERT(PagePrivate(page));
> + ASSERT(folio_test_private(folio));
> btrfs_subpage_start_reader(fs_info, page, page_offset(page), PAGE_SIZE);
> }
>
> @@ -860,6 +862,7 @@ static int attach_extent_buffer_page(struct extent_buffer *eb,
> struct page *page,
> struct btrfs_subpage *prealloc)
> {
> + struct folio *folio = page_folio(page);
> struct btrfs_fs_info *fs_info = eb->fs_info;
> int ret = 0;
>
> @@ -873,22 +876,22 @@ static int attach_extent_buffer_page(struct extent_buffer *eb,
> lockdep_assert_held(&page->mapping->private_lock);
>
> if (fs_info->nodesize >= PAGE_SIZE) {
> - if (!PagePrivate(page))
> - attach_page_private(page, eb);
> + if (!folio_test_private(folio))
> + folio_attach_private(folio, eb);
> else
> - WARN_ON(page->private != (unsigned long)eb);
> + WARN_ON(folio_get_private(folio) != eb);
> return 0;
> }
>
> /* Already mapped, just free prealloc */
> - if (PagePrivate(page)) {
> + if (folio_test_private(folio)) {
> btrfs_free_subpage(prealloc);
> return 0;
> }
>
> if (prealloc)
> /* Has preallocated memory for subpage */
> - attach_page_private(page, prealloc);
> + folio_attach_private(folio, prealloc);
> else
> /* Do new allocation to attach subpage */
> ret = btrfs_attach_subpage(fs_info, page,
> @@ -898,11 +901,12 @@ static int attach_extent_buffer_page(struct extent_buffer *eb,
>
> int set_page_extent_mapped(struct page *page)
> {
> + struct folio *folio = page_folio(page);
> struct btrfs_fs_info *fs_info;
>
> ASSERT(page->mapping);
>
> - if (PagePrivate(page))
> + if (folio_test_private(folio))
> return 0;
>
> fs_info = btrfs_sb(page->mapping->host->i_sb);
> @@ -910,24 +914,25 @@ int set_page_extent_mapped(struct page *page)
> if (btrfs_is_subpage(fs_info, page))
> return btrfs_attach_subpage(fs_info, page, BTRFS_SUBPAGE_DATA);
>
> - attach_page_private(page, (void *)EXTENT_PAGE_PRIVATE);
> + folio_attach_private(folio, (void *)EXTENT_FOLIO_PRIVATE);
> return 0;
> }
>
> void clear_page_extent_mapped(struct page *page)
> {
> + struct folio *folio = page_folio(page);
> struct btrfs_fs_info *fs_info;
>
> ASSERT(page->mapping);
>
> - if (!PagePrivate(page))
> + if (!folio_test_private(folio))
> return;
>
> fs_info = btrfs_sb(page->mapping->host->i_sb);
> if (btrfs_is_subpage(fs_info, page))
> return btrfs_detach_subpage(fs_info, page);
>
> - detach_page_private(page);
> + folio_detach_private(folio);
> }
>
> static struct extent_map *
> @@ -1235,7 +1240,8 @@ static noinline_for_stack int writepage_delalloc(struct btrfs_inode *inode,
> static void find_next_dirty_byte(struct btrfs_fs_info *fs_info,
> struct page *page, u64 *start, u64 *end)
> {
> - struct btrfs_subpage *subpage = (struct btrfs_subpage *)page->private;
> + struct folio *folio = page_folio(page);
> + struct btrfs_subpage *subpage = folio_get_private(folio);
> struct btrfs_subpage_info *spi = fs_info->subpage_info;
> u64 orig_start = *start;
> /* Declare as unsigned long so we can use bitmap ops */
> @@ -1720,6 +1726,7 @@ static noinline_for_stack void write_one_eb(struct extent_buffer *eb,
> static int submit_eb_subpage(struct page *page, struct writeback_control *wbc)
> {
> struct btrfs_fs_info *fs_info = btrfs_sb(page->mapping->host->i_sb);
> + struct folio *folio = page_folio(page);
> int submitted = 0;
> u64 page_start = page_offset(page);
> int bit_start = 0;
> @@ -1727,7 +1734,7 @@ static int submit_eb_subpage(struct page *page, struct writeback_control *wbc)
>
> /* Lock and write each dirty extent buffers in the range */
> while (bit_start < fs_info->subpage_info->bitmap_nr_bits) {
> - struct btrfs_subpage *subpage = (struct btrfs_subpage *)page->private;
> + struct btrfs_subpage *subpage = folio_get_private(folio);
> struct extent_buffer *eb;
> unsigned long flags;
> u64 start;
> @@ -1737,7 +1744,7 @@ static int submit_eb_subpage(struct page *page, struct writeback_control *wbc)
> * in the meantime.
> */
> spin_lock(&page->mapping->private_lock);
> - if (!PagePrivate(page)) {
> + if (!folio_test_private(folio)) {
> spin_unlock(&page->mapping->private_lock);
> break;
> }
> @@ -1802,22 +1809,23 @@ static int submit_eb_page(struct page *page, struct btrfs_eb_write_context *ctx)
> {
> struct writeback_control *wbc = ctx->wbc;
> struct address_space *mapping = page->mapping;
> + struct folio *folio = page_folio(page);
> struct extent_buffer *eb;
> int ret;
>
> - if (!PagePrivate(page))
> + if (!folio_test_private(folio))
> return 0;
>
> if (btrfs_sb(page->mapping->host->i_sb)->nodesize < PAGE_SIZE)
> return submit_eb_subpage(page, wbc);
>
> spin_lock(&mapping->private_lock);
> - if (!PagePrivate(page)) {
> + if (!folio_test_private(folio)) {
> spin_unlock(&mapping->private_lock);
> return 0;
> }
>
> - eb = (struct extent_buffer *)page->private;
> + eb = folio_get_private(folio);
>
> /*
> * Shouldn't happen and normally this would be a BUG_ON but no point
> @@ -3054,12 +3062,13 @@ static int extent_buffer_under_io(const struct extent_buffer *eb)
>
> static bool page_range_has_eb(struct btrfs_fs_info *fs_info, struct page *page)
> {
> + struct folio *folio = page_folio(page);
> struct btrfs_subpage *subpage;
>
> lockdep_assert_held(&page->mapping->private_lock);
>
> - if (PagePrivate(page)) {
> - subpage = (struct btrfs_subpage *)page->private;
> + if (folio_test_private(folio)) {
> + subpage = folio_get_private(folio);
> if (atomic_read(&subpage->eb_refs))
> return true;
> /*
> @@ -3076,15 +3085,16 @@ static void detach_extent_buffer_page(struct extent_buffer *eb, struct page *pag
> {
> struct btrfs_fs_info *fs_info = eb->fs_info;
> const bool mapped = !test_bit(EXTENT_BUFFER_UNMAPPED, &eb->bflags);
> + struct folio *folio = page_folio(page);
>
> /*
> - * For mapped eb, we're going to change the page private, which should
> + * For mapped eb, we're going to change the folio private, which should
> * be done under the private_lock.
> */
> if (mapped)
> spin_lock(&page->mapping->private_lock);
>
> - if (!PagePrivate(page)) {
> + if (!folio_test_private(folio)) {
> if (mapped)
> spin_unlock(&page->mapping->private_lock);
> return;
> @@ -3095,11 +3105,11 @@ static void detach_extent_buffer_page(struct extent_buffer *eb, struct page *pag
> * We do this since we'll remove the pages after we've
> * removed the eb from the radix tree, so we could race
> * and have this page now attached to the new eb. So
> - * only clear page_private if it's still connected to
> + * only clear folio if it's still connected to
> * this eb.
> */
> - if (PagePrivate(page) &&
> - page->private == (unsigned long)eb) {
> + if (folio_test_private(folio) &&
> + folio_get_private(folio) == eb) {
> BUG_ON(test_bit(EXTENT_BUFFER_DIRTY, &eb->bflags));
> BUG_ON(PageDirty(page));
> BUG_ON(PageWriteback(page));
> @@ -3107,7 +3117,7 @@ static void detach_extent_buffer_page(struct extent_buffer *eb, struct page *pag
> * We need to make sure we haven't be attached
> * to a new eb.
> */
> - detach_page_private(page);
> + folio_detach_private(folio);
> }
> if (mapped)
> spin_unlock(&page->mapping->private_lock);
> @@ -3115,9 +3125,9 @@ static void detach_extent_buffer_page(struct extent_buffer *eb, struct page *pag
> }
>
> /*
> - * For subpage, we can have dummy eb with page private. In this case,
> - * we can directly detach the private as such page is only attached to
> - * one dummy eb, no sharing.
> + * For subpage, we can have dummy eb with folio private attached.
> + * In this case, we can directly detach the private as such folio is
> + * only attached to one dummy eb, no sharing.
> */
> if (!mapped) {
> btrfs_detach_subpage(fs_info, page);
> @@ -3127,7 +3137,7 @@ static void detach_extent_buffer_page(struct extent_buffer *eb, struct page *pag
> btrfs_page_dec_eb_refs(fs_info, page);
>
> /*
> - * We can only detach the page private if there are no other ebs in the
> + * We can only detach the folio private if there are no other ebs in the
> * page range and no unfinished IO.
> */
> if (!page_range_has_eb(fs_info, page))
> @@ -3404,6 +3414,7 @@ struct extent_buffer *alloc_test_extent_buffer(struct btrfs_fs_info *fs_info,
> static struct extent_buffer *grab_extent_buffer(
> struct btrfs_fs_info *fs_info, struct page *page)
> {
> + struct folio *folio = page_folio(page);
> struct extent_buffer *exists;
>
> /*
> @@ -3415,21 +3426,21 @@ static struct extent_buffer *grab_extent_buffer(
> return NULL;
>
> /* Page not yet attached to an extent buffer */
> - if (!PagePrivate(page))
> + if (!folio_test_private(folio))
> return NULL;
>
> /*
> * We could have already allocated an eb for this page and attached one
> * so lets see if we can get a ref on the existing eb, and if we can we
> * know it's good and we can just return that one, else we know we can
> - * just overwrite page->private.
> + * just overwrite folio private.
> */
> - exists = (struct extent_buffer *)page->private;
> + exists = folio_get_private(folio);
> if (atomic_inc_not_zero(&exists->refs))
> return exists;
>
> WARN_ON(PageDirty(page));
> - detach_page_private(page);
> + folio_detach_private(folio);
> return NULL;
> }
>
> @@ -3514,7 +3525,7 @@ struct extent_buffer *alloc_extent_buffer(struct btrfs_fs_info *fs_info,
> num_pages = num_extent_pages(eb);
>
> /*
> - * Preallocate page->private for subpage case, so that we won't
> + * Preallocate folio private for subpage case, so that we won't
> * allocate memory with private_lock nor page lock hold.
> *
> * The memory will be freed by attach_extent_buffer_page() or freed
> @@ -3551,7 +3562,7 @@ struct extent_buffer *alloc_extent_buffer(struct btrfs_fs_info *fs_info,
> ASSERT(!ret);
> /*
> * To inform we have extra eb under allocation, so that
> - * detach_extent_buffer_page() won't release the page private
> + * detach_extent_buffer_page() won't release the folio private
> * when the eb hasn't yet been inserted into radix tree.
> *
> * The ref will be decreased when the eb released the page, in
> @@ -4569,7 +4580,7 @@ static int try_release_subpage_extent_buffer(struct page *page)
> struct extent_buffer *eb = NULL;
>
> /*
> - * Unlike try_release_extent_buffer() which uses page->private
> + * Unlike try_release_extent_buffer() which uses folio private
> * to grab buffer, for subpage case we rely on radix tree, thus
> * we need to ensure radix tree consistency.
> *
> @@ -4609,17 +4620,17 @@ static int try_release_subpage_extent_buffer(struct page *page)
>
> /*
> * Here we don't care about the return value, we will always
> - * check the page private at the end. And
> + * check the folio private at the end. And
> * release_extent_buffer() will release the refs_lock.
> */
> release_extent_buffer(eb);
> }
> /*
> - * Finally to check if we have cleared page private, as if we have
> - * released all ebs in the page, the page private should be cleared now.
> + * Finally to check if we have cleared folio private, as if we have
> + * released all ebs in the page, the folio private should be cleared now.
> */
> spin_lock(&page->mapping->private_lock);
> - if (!PagePrivate(page))
> + if (!folio_test_private(page_folio(page)))
> ret = 1;
> else
> ret = 0;
> @@ -4630,22 +4641,23 @@ static int try_release_subpage_extent_buffer(struct page *page)
>
> int try_release_extent_buffer(struct page *page)
> {
> + struct folio *folio = page_folio(page);
> struct extent_buffer *eb;
>
> if (btrfs_sb(page->mapping->host->i_sb)->nodesize < PAGE_SIZE)
> return try_release_subpage_extent_buffer(page);
>
> /*
> - * We need to make sure nobody is changing page->private, as we rely on
> - * page->private as the pointer to extent buffer.
> + * We need to make sure nobody is changing folio private, as we rely on
> + * folio private as the pointer to extent buffer.
> */
> spin_lock(&page->mapping->private_lock);
> - if (!PagePrivate(page)) {
> + if (!folio_test_private(folio)) {
> spin_unlock(&page->mapping->private_lock);
> return 1;
> }
>
> - eb = (struct extent_buffer *)page->private;
> + eb = folio_get_private(folio);
> BUG_ON(!eb);
>
> /*
> diff --git a/fs/btrfs/extent_io.h b/fs/btrfs/extent_io.h
> index a88374ad248f..6531285ef0bc 100644
> --- a/fs/btrfs/extent_io.h
> +++ b/fs/btrfs/extent_io.h
> @@ -43,10 +43,10 @@ enum {
> };
>
> /*
> - * page->private values. Every page that is controlled by the extent
> - * map has page->private set to one.
> + * folio private values. Every page that is controlled by the extent
> + * map has folio private set to this value.
> */
> -#define EXTENT_PAGE_PRIVATE 1
> +#define EXTENT_FOLIO_PRIVATE 1
>
> /*
> * The extent buffer bitmap operations are done with byte granularity instead of
> diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
> index f47731c45bb5..6197f585cdff 100644
> --- a/fs/btrfs/file.c
> +++ b/fs/btrfs/file.c
> @@ -869,9 +869,10 @@ static int prepare_uptodate_page(struct inode *inode,
> * released.
> *
> * The private flag check is essential for subpage as we need
> - * to store extra bitmap using page->private.
> + * to store extra bitmap using folio private.
> */
> - if (page->mapping != inode->i_mapping || !PagePrivate(page)) {
> + if (page->mapping != inode->i_mapping ||
> + !folio_test_private(folio)) {
> unlock_page(page);
> return -EAGAIN;
> }
> diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
> index 9f5a9894f88f..40f64322b1f1 100644
> --- a/fs/btrfs/inode.c
> +++ b/fs/btrfs/inode.c
> @@ -4725,7 +4725,7 @@ int btrfs_truncate_block(struct btrfs_inode *inode, loff_t from, loff_t len,
> /*
> * We unlock the page after the io is completed and then re-lock it
> * above. release_folio() could have come in between that and cleared
> - * PagePrivate(), but left the page in the mapping. Set the page mapped
> + * folio private, but left the page in the mapping. Set the page mapped
> * here to make sure it's properly set for the subpage stuff.
> */
> ret = set_page_extent_mapped(page);
> @@ -7851,13 +7851,14 @@ static void btrfs_readahead(struct readahead_control *rac)
> static void wait_subpage_spinlock(struct page *page)
> {
> struct btrfs_fs_info *fs_info = btrfs_sb(page->mapping->host->i_sb);
> + struct folio *folio = page_folio(page);
> struct btrfs_subpage *subpage;
>
> if (!btrfs_is_subpage(fs_info, page))
> return;
>
> - ASSERT(PagePrivate(page) && page->private);
> - subpage = (struct btrfs_subpage *)page->private;
> + ASSERT(folio_test_private(folio) && folio_get_private(folio));
> + subpage = folio_get_private(folio);
>
> /*
> * This may look insane as we just acquire the spinlock and release it,
> diff --git a/fs/btrfs/subpage.c b/fs/btrfs/subpage.c
> index 1b999c6e4193..72d8dd516db9 100644
> --- a/fs/btrfs/subpage.c
> +++ b/fs/btrfs/subpage.c
> @@ -118,6 +118,7 @@ void btrfs_init_subpage_info(struct btrfs_subpage_info *subpage_info, u32 sector
> int btrfs_attach_subpage(const struct btrfs_fs_info *fs_info,
> struct page *page, enum btrfs_subpage_type type)
> {
> + struct folio *folio = page_folio(page);
> struct btrfs_subpage *subpage;
>
> /*
> @@ -127,28 +128,29 @@ int btrfs_attach_subpage(const struct btrfs_fs_info *fs_info,
> if (page->mapping)
> ASSERT(PageLocked(page));
>
> - /* Either not subpage, or the page already has private attached */
> - if (!btrfs_is_subpage(fs_info, page) || PagePrivate(page))
> + /* Either not subpage, or the folio already has private attached */
> + if (!btrfs_is_subpage(fs_info, page) || folio_test_private(folio))
> return 0;
>
> subpage = btrfs_alloc_subpage(fs_info, type);
> if (IS_ERR(subpage))
> return PTR_ERR(subpage);
>
> - attach_page_private(page, subpage);
> + folio_attach_private(folio, subpage);
> return 0;
> }
>
> void btrfs_detach_subpage(const struct btrfs_fs_info *fs_info,
> struct page *page)
> {
> + struct folio *folio = page_folio(page);
> struct btrfs_subpage *subpage;
>
> /* Either not subpage, or already detached */
> - if (!btrfs_is_subpage(fs_info, page) || !PagePrivate(page))
> + if (!btrfs_is_subpage(fs_info, page) || !folio_test_private(folio))
> return;
>
> - subpage = detach_page_private(page);
> + subpage = folio_detach_private(folio);
> ASSERT(subpage);
> btrfs_free_subpage(subpage);
> }
> @@ -188,36 +190,38 @@ void btrfs_free_subpage(struct btrfs_subpage *subpage)
> * This is important for eb allocation, to prevent race with last eb freeing
> * of the same page.
> * With the eb_refs increased before the eb inserted into radix tree,
> - * detach_extent_buffer_page() won't detach the page private while we're still
> + * detach_extent_buffer_page() won't detach the folio private while we're still
> * allocating the extent buffer.
> */
> void btrfs_page_inc_eb_refs(const struct btrfs_fs_info *fs_info,
> struct page *page)
> {
> + struct folio *folio = page_folio(page);
> struct btrfs_subpage *subpage;
>
> if (!btrfs_is_subpage(fs_info, page))
> return;
>
> - ASSERT(PagePrivate(page) && page->mapping);
> + ASSERT(folio_test_private(folio) && page->mapping);
> lockdep_assert_held(&page->mapping->private_lock);
>
> - subpage = (struct btrfs_subpage *)page->private;
> + subpage = folio_get_private(folio);
> atomic_inc(&subpage->eb_refs);
> }
>
> void btrfs_page_dec_eb_refs(const struct btrfs_fs_info *fs_info,
> struct page *page)
> {
> + struct folio *folio = page_folio(page);
> struct btrfs_subpage *subpage;
>
> if (!btrfs_is_subpage(fs_info, page))
> return;
>
> - ASSERT(PagePrivate(page) && page->mapping);
> + ASSERT(folio_test_private(folio) && page->mapping);
> lockdep_assert_held(&page->mapping->private_lock);
>
> - subpage = (struct btrfs_subpage *)page->private;
> + subpage = folio_get_private(folio);
> ASSERT(atomic_read(&subpage->eb_refs));
> atomic_dec(&subpage->eb_refs);
> }
> @@ -225,8 +229,10 @@ void btrfs_page_dec_eb_refs(const struct btrfs_fs_info *fs_info,
> static void btrfs_subpage_assert(const struct btrfs_fs_info *fs_info,
> struct page *page, u64 start, u32 len)
> {
> + struct folio *folio = page_folio(page);
> +
> /* Basic checks */
> - ASSERT(PagePrivate(page) && page->private);
> + ASSERT(folio_test_private(folio) && folio_get_private(folio));
> ASSERT(IS_ALIGNED(start, fs_info->sectorsize) &&
> IS_ALIGNED(len, fs_info->sectorsize));
> /*
> @@ -241,7 +247,8 @@ static void btrfs_subpage_assert(const struct btrfs_fs_info *fs_info,
> void btrfs_subpage_start_reader(const struct btrfs_fs_info *fs_info,
> struct page *page, u64 start, u32 len)
> {
> - struct btrfs_subpage *subpage = (struct btrfs_subpage *)page->private;
> + struct folio *folio = page_folio(page);
> + struct btrfs_subpage *subpage = folio_get_private(folio);
> const int nbits = len >> fs_info->sectorsize_bits;
>
> btrfs_subpage_assert(fs_info, page, start, len);
> @@ -252,7 +259,8 @@ void btrfs_subpage_start_reader(const struct btrfs_fs_info *fs_info,
> void btrfs_subpage_end_reader(const struct btrfs_fs_info *fs_info,
> struct page *page, u64 start, u32 len)
> {
> - struct btrfs_subpage *subpage = (struct btrfs_subpage *)page->private;
> + struct folio *folio = page_folio(page);
> + struct btrfs_subpage *subpage = folio_get_private(folio);
> const int nbits = len >> fs_info->sectorsize_bits;
> bool is_data;
> bool last;
> @@ -294,7 +302,8 @@ static void btrfs_subpage_clamp_range(struct page *page, u64 *start, u32 *len)
> void btrfs_subpage_start_writer(const struct btrfs_fs_info *fs_info,
> struct page *page, u64 start, u32 len)
> {
> - struct btrfs_subpage *subpage = (struct btrfs_subpage *)page->private;
> + struct folio *folio = page_folio(page);
> + struct btrfs_subpage *subpage = folio_get_private(folio);
> const int nbits = (len >> fs_info->sectorsize_bits);
> int ret;
>
> @@ -308,7 +317,8 @@ void btrfs_subpage_start_writer(const struct btrfs_fs_info *fs_info,
> bool btrfs_subpage_end_and_test_writer(const struct btrfs_fs_info *fs_info,
> struct page *page, u64 start, u32 len)
> {
> - struct btrfs_subpage *subpage = (struct btrfs_subpage *)page->private;
> + struct folio *folio = page_folio(page);
> + struct btrfs_subpage *subpage = folio_get_private(folio);
> const int nbits = (len >> fs_info->sectorsize_bits);
>
> btrfs_subpage_assert(fs_info, page, start, len);
> @@ -340,12 +350,14 @@ bool btrfs_subpage_end_and_test_writer(const struct btrfs_fs_info *fs_info,
> int btrfs_page_start_writer_lock(const struct btrfs_fs_info *fs_info,
> struct page *page, u64 start, u32 len)
> {
> + struct folio *folio = page_folio(page);
> +
> if (unlikely(!fs_info) || !btrfs_is_subpage(fs_info, page)) {
> lock_page(page);
> return 0;
> }
> lock_page(page);
> - if (!PagePrivate(page) || !page->private) {
> + if (!folio_test_private(folio) || !folio_get_private(folio)) {
> unlock_page(page);
> return -EAGAIN;
> }
> @@ -387,7 +399,8 @@ void btrfs_page_end_writer_lock(const struct btrfs_fs_info *fs_info,
> void btrfs_subpage_set_uptodate(const struct btrfs_fs_info *fs_info,
> struct page *page, u64 start, u32 len)
> {
> - struct btrfs_subpage *subpage = (struct btrfs_subpage *)page->private;
> + struct folio *folio = page_folio(page);
> + struct btrfs_subpage *subpage = folio_get_private(folio);
> unsigned int start_bit = subpage_calc_start_bit(fs_info, page,
> uptodate, start, len);
> unsigned long flags;
> @@ -402,7 +415,8 @@ void btrfs_subpage_set_uptodate(const struct btrfs_fs_info *fs_info,
> void btrfs_subpage_clear_uptodate(const struct btrfs_fs_info *fs_info,
> struct page *page, u64 start, u32 len)
> {
> - struct btrfs_subpage *subpage = (struct btrfs_subpage *)page->private;
> + struct folio *folio = page_folio(page);
> + struct btrfs_subpage *subpage = folio_get_private(folio);
> unsigned int start_bit = subpage_calc_start_bit(fs_info, page,
> uptodate, start, len);
> unsigned long flags;
> @@ -416,7 +430,8 @@ void btrfs_subpage_clear_uptodate(const struct btrfs_fs_info *fs_info,
> void btrfs_subpage_set_dirty(const struct btrfs_fs_info *fs_info,
> struct page *page, u64 start, u32 len)
> {
> - struct btrfs_subpage *subpage = (struct btrfs_subpage *)page->private;
> + struct folio *folio = page_folio(page);
> + struct btrfs_subpage *subpage = folio_get_private(folio);
> unsigned int start_bit = subpage_calc_start_bit(fs_info, page,
> dirty, start, len);
> unsigned long flags;
> @@ -440,7 +455,8 @@ void btrfs_subpage_set_dirty(const struct btrfs_fs_info *fs_info,
> bool btrfs_subpage_clear_and_test_dirty(const struct btrfs_fs_info *fs_info,
> struct page *page, u64 start, u32 len)
> {
> - struct btrfs_subpage *subpage = (struct btrfs_subpage *)page->private;
> + struct folio *folio = page_folio(page);
> + struct btrfs_subpage *subpage = folio_get_private(folio);
> unsigned int start_bit = subpage_calc_start_bit(fs_info, page,
> dirty, start, len);
> unsigned long flags;
> @@ -467,7 +483,8 @@ void btrfs_subpage_clear_dirty(const struct btrfs_fs_info *fs_info,
> void btrfs_subpage_set_writeback(const struct btrfs_fs_info *fs_info,
> struct page *page, u64 start, u32 len)
> {
> - struct btrfs_subpage *subpage = (struct btrfs_subpage *)page->private;
> + struct folio *folio = page_folio(page);
> + struct btrfs_subpage *subpage = folio_get_private(folio);
> unsigned int start_bit = subpage_calc_start_bit(fs_info, page,
> writeback, start, len);
> unsigned long flags;
> @@ -481,7 +498,8 @@ void btrfs_subpage_set_writeback(const struct btrfs_fs_info *fs_info,
> void btrfs_subpage_clear_writeback(const struct btrfs_fs_info *fs_info,
> struct page *page, u64 start, u32 len)
> {
> - struct btrfs_subpage *subpage = (struct btrfs_subpage *)page->private;
> + struct folio *folio = page_folio(page);
> + struct btrfs_subpage *subpage = folio_get_private(folio);
> unsigned int start_bit = subpage_calc_start_bit(fs_info, page,
> writeback, start, len);
> unsigned long flags;
> @@ -498,7 +516,8 @@ void btrfs_subpage_clear_writeback(const struct btrfs_fs_info *fs_info,
> void btrfs_subpage_set_ordered(const struct btrfs_fs_info *fs_info,
> struct page *page, u64 start, u32 len)
> {
> - struct btrfs_subpage *subpage = (struct btrfs_subpage *)page->private;
> + struct folio *folio = page_folio(page);
> + struct btrfs_subpage *subpage = folio_get_private(folio);
> unsigned int start_bit = subpage_calc_start_bit(fs_info, page,
> ordered, start, len);
> unsigned long flags;
> @@ -512,7 +531,8 @@ void btrfs_subpage_set_ordered(const struct btrfs_fs_info *fs_info,
> void btrfs_subpage_clear_ordered(const struct btrfs_fs_info *fs_info,
> struct page *page, u64 start, u32 len)
> {
> - struct btrfs_subpage *subpage = (struct btrfs_subpage *)page->private;
> + struct folio *folio = page_folio(page);
> + struct btrfs_subpage *subpage = folio_get_private(folio);
> unsigned int start_bit = subpage_calc_start_bit(fs_info, page,
> ordered, start, len);
> unsigned long flags;
> @@ -527,7 +547,8 @@ void btrfs_subpage_clear_ordered(const struct btrfs_fs_info *fs_info,
> void btrfs_subpage_set_checked(const struct btrfs_fs_info *fs_info,
> struct page *page, u64 start, u32 len)
> {
> - struct btrfs_subpage *subpage = (struct btrfs_subpage *)page->private;
> + struct folio *folio = page_folio(page);
> + struct btrfs_subpage *subpage = folio_get_private(folio);
> unsigned int start_bit = subpage_calc_start_bit(fs_info, page,
> checked, start, len);
> unsigned long flags;
> @@ -542,7 +563,8 @@ void btrfs_subpage_set_checked(const struct btrfs_fs_info *fs_info,
> void btrfs_subpage_clear_checked(const struct btrfs_fs_info *fs_info,
> struct page *page, u64 start, u32 len)
> {
> - struct btrfs_subpage *subpage = (struct btrfs_subpage *)page->private;
> + struct folio *folio = page_folio(page);
> + struct btrfs_subpage *subpage = folio_get_private(folio);
> unsigned int start_bit = subpage_calc_start_bit(fs_info, page,
> checked, start, len);
> unsigned long flags;
> @@ -561,7 +583,8 @@ void btrfs_subpage_clear_checked(const struct btrfs_fs_info *fs_info,
> bool btrfs_subpage_test_##name(const struct btrfs_fs_info *fs_info, \
> struct page *page, u64 start, u32 len) \
> { \
> - struct btrfs_subpage *subpage = (struct btrfs_subpage *)page->private; \
> + struct folio *folio = page_folio(page); \
> + struct btrfs_subpage *subpage = folio_get_private(folio); \
> unsigned int start_bit = subpage_calc_start_bit(fs_info, page, \
> name, start, len); \
> unsigned long flags; \
> @@ -656,7 +679,8 @@ IMPLEMENT_BTRFS_PAGE_OPS(checked, SetPageChecked, ClearPageChecked, PageChecked)
> void btrfs_page_assert_not_dirty(const struct btrfs_fs_info *fs_info,
> struct page *page)
> {
> - struct btrfs_subpage *subpage = (struct btrfs_subpage *)page->private;
> + struct folio *folio = page_folio(page);
> + struct btrfs_subpage *subpage = folio_get_private(folio);
>
> if (!IS_ENABLED(CONFIG_BTRFS_ASSERT))
> return;
> @@ -665,7 +689,7 @@ void btrfs_page_assert_not_dirty(const struct btrfs_fs_info *fs_info,
> if (!btrfs_is_subpage(fs_info, page))
> return;
>
> - ASSERT(PagePrivate(page) && page->private);
> + ASSERT(folio_test_private(folio) && folio_get_private(folio));
> ASSERT(subpage_test_bitmap_all_zero(fs_info, subpage, dirty));
> }
>
> @@ -687,6 +711,7 @@ void btrfs_page_assert_not_dirty(const struct btrfs_fs_info *fs_info,
> void btrfs_page_unlock_writer(struct btrfs_fs_info *fs_info, struct page *page,
> u64 start, u32 len)
> {
> + struct folio *folio = page_folio(page);
> struct btrfs_subpage *subpage;
>
> ASSERT(PageLocked(page));
> @@ -694,8 +719,8 @@ void btrfs_page_unlock_writer(struct btrfs_fs_info *fs_info, struct page *page,
> if (!btrfs_is_subpage(fs_info, page))
> return unlock_page(page);
>
> - ASSERT(PagePrivate(page) && page->private);
> - subpage = (struct btrfs_subpage *)page->private;
> + ASSERT(folio_test_private(folio) && folio_get_private(folio));
> + subpage = folio_get_private(folio);
>
> /*
> * For subpage case, there are two types of locked page. With or
> @@ -720,6 +745,7 @@ void __cold btrfs_subpage_dump_bitmap(const struct btrfs_fs_info *fs_info,
> struct page *page, u64 start, u32 len)
> {
> struct btrfs_subpage_info *subpage_info = fs_info->subpage_info;
> + struct folio *folio = page_folio(page);
> struct btrfs_subpage *subpage;
> unsigned long uptodate_bitmap;
> unsigned long error_bitmap;
> @@ -729,9 +755,9 @@ void __cold btrfs_subpage_dump_bitmap(const struct btrfs_fs_info *fs_info,
> unsigned long checked_bitmap;
> unsigned long flags;
>
> - ASSERT(PagePrivate(page) && page->private);
> + ASSERT(folio_test_private(folio) && folio_get_private(folio));
> ASSERT(subpage_info);
> - subpage = (struct btrfs_subpage *)page->private;
> + subpage = folio_get_private(folio);
>
> spin_lock_irqsave(&subpage->lock, flags);
> GET_SUBPAGE_BITMAP(subpage, subpage_info, uptodate, &uptodate_bitmap);
> --
> 2.42.1
>
>
Patch makes sense to me.
Reviewed-by: Neal Gompa <neal@gompa.dev>
--
真実はいつも一つ!/ Always, there's only one truth!
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] btrfs: migrate to use folio private instead of page private
2023-11-17 3:54 [PATCH] btrfs: migrate to use folio private instead of page private Qu Wenruo
2023-11-17 19:08 ` Josef Bacik
2023-11-17 23:56 ` Neal Gompa
@ 2023-11-20 7:45 ` Johannes Thumshirn
2023-11-21 12:58 ` David Sterba
3 siblings, 0 replies; 5+ messages in thread
From: Johannes Thumshirn @ 2023-11-20 7:45 UTC (permalink / raw)
To: Qu Wenruo, linux-btrfs@vger.kernel.org
Looks good,
Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] btrfs: migrate to use folio private instead of page private
2023-11-17 3:54 [PATCH] btrfs: migrate to use folio private instead of page private Qu Wenruo
` (2 preceding siblings ...)
2023-11-20 7:45 ` Johannes Thumshirn
@ 2023-11-21 12:58 ` David Sterba
3 siblings, 0 replies; 5+ messages in thread
From: David Sterba @ 2023-11-21 12:58 UTC (permalink / raw)
To: Qu Wenruo; +Cc: linux-btrfs
On Fri, Nov 17, 2023 at 02:24:14PM +1030, Qu Wenruo wrote:
> As a cleanup and preparation for future folio migration, this patch
> would replace all page->private to folio version.
> This includes:
>
> - PagePrivate()
> -> folio_test_private()
>
> - page->private
> -> folio_get_private()
>
> - attach_page_private()
> -> folio_attach_private()
>
> - detach_page_private()
> -> folio_detach_private()
>
> Since we're here, also remove the forced cast on page->private, since
> it's (void *) already, we don't really need to do the cast.
>
> For now even if we missed some call sites, it won't cause any problem
> yet, as we're only using order 0 folio (single page), thus all those
> folio/page flags should be synced.
>
> But for the future conversion to utilize higher order folio, the page
> <-> folio flag sync is no longer guaranteed, thus we have to migrate to
> utilize folio flags.
>
> Signed-off-by: Qu Wenruo <wqu@suse.com>
Added to misc-next, thanks.
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2023-11-21 13:05 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-11-17 3:54 [PATCH] btrfs: migrate to use folio private instead of page private Qu Wenruo
2023-11-17 19:08 ` Josef Bacik
2023-11-17 23:56 ` Neal Gompa
2023-11-20 7:45 ` Johannes Thumshirn
2023-11-21 12:58 ` David Sterba
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.