mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-01-06 05:13:18 +00:00
mm/migrate: Convert buffer_migrate_page() to buffer_migrate_folio()
Use a folio throughout __buffer_migrate_folio(), add kernel-doc for buffer_migrate_folio() and buffer_migrate_folio_norefs(), move their declarations to buffer.h and switch all filesystems that have wired them up. Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org> Reviewed-by: Christoph Hellwig <hch@lst.de>
This commit is contained in:
parent
2be7fa10c0
commit
67235182a4
@ -417,7 +417,7 @@ const struct address_space_operations def_blk_aops = {
|
||||
.write_end = blkdev_write_end,
|
||||
.writepages = blkdev_writepages,
|
||||
.direct_IO = blkdev_direct_IO,
|
||||
.migratepage = buffer_migrate_page_norefs,
|
||||
.migrate_folio = buffer_migrate_folio_norefs,
|
||||
.is_dirty_writeback = buffer_check_dirty_writeback,
|
||||
};
|
||||
|
||||
|
@ -973,7 +973,7 @@ const struct address_space_operations ext2_aops = {
|
||||
.bmap = ext2_bmap,
|
||||
.direct_IO = ext2_direct_IO,
|
||||
.writepages = ext2_writepages,
|
||||
.migratepage = buffer_migrate_page,
|
||||
.migrate_folio = buffer_migrate_folio,
|
||||
.is_partially_uptodate = block_is_partially_uptodate,
|
||||
.error_remove_page = generic_error_remove_page,
|
||||
};
|
||||
@ -989,7 +989,7 @@ const struct address_space_operations ext2_nobh_aops = {
|
||||
.bmap = ext2_bmap,
|
||||
.direct_IO = ext2_direct_IO,
|
||||
.writepages = ext2_writepages,
|
||||
.migratepage = buffer_migrate_page,
|
||||
.migrate_folio = buffer_migrate_folio,
|
||||
.error_remove_page = generic_error_remove_page,
|
||||
};
|
||||
|
||||
|
@ -3633,7 +3633,7 @@ static const struct address_space_operations ext4_aops = {
|
||||
.invalidate_folio = ext4_invalidate_folio,
|
||||
.release_folio = ext4_release_folio,
|
||||
.direct_IO = noop_direct_IO,
|
||||
.migratepage = buffer_migrate_page,
|
||||
.migrate_folio = buffer_migrate_folio,
|
||||
.is_partially_uptodate = block_is_partially_uptodate,
|
||||
.error_remove_page = generic_error_remove_page,
|
||||
.swap_activate = ext4_iomap_swap_activate,
|
||||
@ -3668,7 +3668,7 @@ static const struct address_space_operations ext4_da_aops = {
|
||||
.invalidate_folio = ext4_invalidate_folio,
|
||||
.release_folio = ext4_release_folio,
|
||||
.direct_IO = noop_direct_IO,
|
||||
.migratepage = buffer_migrate_page,
|
||||
.migrate_folio = buffer_migrate_folio,
|
||||
.is_partially_uptodate = block_is_partially_uptodate,
|
||||
.error_remove_page = generic_error_remove_page,
|
||||
.swap_activate = ext4_iomap_swap_activate,
|
||||
|
@ -1659,7 +1659,7 @@ const struct address_space_operations ntfs_normal_aops = {
|
||||
.dirty_folio = block_dirty_folio,
|
||||
#endif /* NTFS_RW */
|
||||
.bmap = ntfs_bmap,
|
||||
.migratepage = buffer_migrate_page,
|
||||
.migrate_folio = buffer_migrate_folio,
|
||||
.is_partially_uptodate = block_is_partially_uptodate,
|
||||
.error_remove_page = generic_error_remove_page,
|
||||
};
|
||||
@ -1673,7 +1673,7 @@ const struct address_space_operations ntfs_compressed_aops = {
|
||||
.writepage = ntfs_writepage,
|
||||
.dirty_folio = block_dirty_folio,
|
||||
#endif /* NTFS_RW */
|
||||
.migratepage = buffer_migrate_page,
|
||||
.migrate_folio = buffer_migrate_folio,
|
||||
.is_partially_uptodate = block_is_partially_uptodate,
|
||||
.error_remove_page = generic_error_remove_page,
|
||||
};
|
||||
@ -1688,7 +1688,7 @@ const struct address_space_operations ntfs_mst_aops = {
|
||||
.writepage = ntfs_writepage, /* Write dirty page to disk. */
|
||||
.dirty_folio = filemap_dirty_folio,
|
||||
#endif /* NTFS_RW */
|
||||
.migratepage = buffer_migrate_page,
|
||||
.migrate_folio = buffer_migrate_folio,
|
||||
.is_partially_uptodate = block_is_partially_uptodate,
|
||||
.error_remove_page = generic_error_remove_page,
|
||||
};
|
||||
|
@ -2462,7 +2462,7 @@ const struct address_space_operations ocfs2_aops = {
|
||||
.direct_IO = ocfs2_direct_IO,
|
||||
.invalidate_folio = block_invalidate_folio,
|
||||
.release_folio = ocfs2_release_folio,
|
||||
.migratepage = buffer_migrate_page,
|
||||
.migrate_folio = buffer_migrate_folio,
|
||||
.is_partially_uptodate = block_is_partially_uptodate,
|
||||
.error_remove_page = generic_error_remove_page,
|
||||
};
|
||||
|
@ -267,6 +267,16 @@ int nobh_truncate_page(struct address_space *, loff_t, get_block_t *);
|
||||
int nobh_writepage(struct page *page, get_block_t *get_block,
|
||||
struct writeback_control *wbc);
|
||||
|
||||
#ifdef CONFIG_MIGRATION
|
||||
extern int buffer_migrate_folio(struct address_space *,
|
||||
struct folio *dst, struct folio *src, enum migrate_mode);
|
||||
extern int buffer_migrate_folio_norefs(struct address_space *,
|
||||
struct folio *dst, struct folio *src, enum migrate_mode);
|
||||
#else
|
||||
#define buffer_migrate_folio NULL
|
||||
#define buffer_migrate_folio_norefs NULL
|
||||
#endif
|
||||
|
||||
void buffer_init(void);
|
||||
|
||||
/*
|
||||
|
@ -3215,18 +3215,6 @@ extern int generic_check_addressable(unsigned, u64);
|
||||
|
||||
extern void generic_set_encrypted_ci_d_ops(struct dentry *dentry);
|
||||
|
||||
#ifdef CONFIG_MIGRATION
|
||||
extern int buffer_migrate_page(struct address_space *,
|
||||
struct page *, struct page *,
|
||||
enum migrate_mode);
|
||||
extern int buffer_migrate_page_norefs(struct address_space *,
|
||||
struct page *, struct page *,
|
||||
enum migrate_mode);
|
||||
#else
|
||||
#define buffer_migrate_page NULL
|
||||
#define buffer_migrate_page_norefs NULL
|
||||
#endif
|
||||
|
||||
int may_setattr(struct user_namespace *mnt_userns, struct inode *inode,
|
||||
unsigned int ia_valid);
|
||||
int setattr_prepare(struct user_namespace *, struct dentry *, struct iattr *);
|
||||
|
76
mm/migrate.c
76
mm/migrate.c
@ -656,23 +656,23 @@ static bool buffer_migrate_lock_buffers(struct buffer_head *head,
|
||||
return true;
|
||||
}
|
||||
|
||||
static int __buffer_migrate_page(struct address_space *mapping,
|
||||
struct page *newpage, struct page *page, enum migrate_mode mode,
|
||||
static int __buffer_migrate_folio(struct address_space *mapping,
|
||||
struct folio *dst, struct folio *src, enum migrate_mode mode,
|
||||
bool check_refs)
|
||||
{
|
||||
struct buffer_head *bh, *head;
|
||||
int rc;
|
||||
int expected_count;
|
||||
|
||||
if (!page_has_buffers(page))
|
||||
return migrate_page(mapping, newpage, page, mode);
|
||||
head = folio_buffers(src);
|
||||
if (!head)
|
||||
return migrate_page(mapping, &dst->page, &src->page, mode);
|
||||
|
||||
/* Check whether page does not have extra refs before we do more work */
|
||||
expected_count = expected_page_refs(mapping, page);
|
||||
if (page_count(page) != expected_count)
|
||||
expected_count = expected_page_refs(mapping, &src->page);
|
||||
if (folio_ref_count(src) != expected_count)
|
||||
return -EAGAIN;
|
||||
|
||||
head = page_buffers(page);
|
||||
if (!buffer_migrate_lock_buffers(head, mode))
|
||||
return -EAGAIN;
|
||||
|
||||
@ -703,23 +703,22 @@ static int __buffer_migrate_page(struct address_space *mapping,
|
||||
}
|
||||
}
|
||||
|
||||
rc = migrate_page_move_mapping(mapping, newpage, page, 0);
|
||||
rc = folio_migrate_mapping(mapping, dst, src, 0);
|
||||
if (rc != MIGRATEPAGE_SUCCESS)
|
||||
goto unlock_buffers;
|
||||
|
||||
attach_page_private(newpage, detach_page_private(page));
|
||||
folio_attach_private(dst, folio_detach_private(src));
|
||||
|
||||
bh = head;
|
||||
do {
|
||||
set_bh_page(bh, newpage, bh_offset(bh));
|
||||
set_bh_page(bh, &dst->page, bh_offset(bh));
|
||||
bh = bh->b_this_page;
|
||||
|
||||
} while (bh != head);
|
||||
|
||||
if (mode != MIGRATE_SYNC_NO_COPY)
|
||||
migrate_page_copy(newpage, page);
|
||||
folio_migrate_copy(dst, src);
|
||||
else
|
||||
migrate_page_states(newpage, page);
|
||||
folio_migrate_flags(dst, src);
|
||||
|
||||
rc = MIGRATEPAGE_SUCCESS;
|
||||
unlock_buffers:
|
||||
@ -729,34 +728,51 @@ static int __buffer_migrate_page(struct address_space *mapping,
|
||||
do {
|
||||
unlock_buffer(bh);
|
||||
bh = bh->b_this_page;
|
||||
|
||||
} while (bh != head);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
* Migration function for pages with buffers. This function can only be used
|
||||
* if the underlying filesystem guarantees that no other references to "page"
|
||||
* exist. For example attached buffer heads are accessed only under page lock.
|
||||
/**
|
||||
* buffer_migrate_folio() - Migration function for folios with buffers.
|
||||
* @mapping: The address space containing @src.
|
||||
* @dst: The folio to migrate to.
|
||||
* @src: The folio to migrate from.
|
||||
* @mode: How to migrate the folio.
|
||||
*
|
||||
* This function can only be used if the underlying filesystem guarantees
|
||||
* that no other references to @src exist. For example attached buffer
|
||||
* heads are accessed only under the folio lock. If your filesystem cannot
|
||||
* provide this guarantee, buffer_migrate_folio_norefs() may be more
|
||||
* appropriate.
|
||||
*
|
||||
* Return: 0 on success or a negative errno on failure.
|
||||
*/
|
||||
int buffer_migrate_page(struct address_space *mapping,
|
||||
struct page *newpage, struct page *page, enum migrate_mode mode)
|
||||
int buffer_migrate_folio(struct address_space *mapping,
|
||||
struct folio *dst, struct folio *src, enum migrate_mode mode)
|
||||
{
|
||||
return __buffer_migrate_page(mapping, newpage, page, mode, false);
|
||||
return __buffer_migrate_folio(mapping, dst, src, mode, false);
|
||||
}
|
||||
EXPORT_SYMBOL(buffer_migrate_page);
|
||||
EXPORT_SYMBOL(buffer_migrate_folio);
|
||||
|
||||
/*
|
||||
* Same as above except that this variant is more careful and checks that there
|
||||
* are also no buffer head references. This function is the right one for
|
||||
* mappings where buffer heads are directly looked up and referenced (such as
|
||||
* block device mappings).
|
||||
/**
|
||||
* buffer_migrate_folio_norefs() - Migration function for folios with buffers.
|
||||
* @mapping: The address space containing @src.
|
||||
* @dst: The folio to migrate to.
|
||||
* @src: The folio to migrate from.
|
||||
* @mode: How to migrate the folio.
|
||||
*
|
||||
* Like buffer_migrate_folio() except that this variant is more careful
|
||||
* and checks that there are also no buffer head references. This function
|
||||
* is the right one for mappings where buffer heads are directly looked
|
||||
* up and referenced (such as block device mappings).
|
||||
*
|
||||
* Return: 0 on success or a negative errno on failure.
|
||||
*/
|
||||
int buffer_migrate_page_norefs(struct address_space *mapping,
|
||||
struct page *newpage, struct page *page, enum migrate_mode mode)
|
||||
int buffer_migrate_folio_norefs(struct address_space *mapping,
|
||||
struct folio *dst, struct folio *src, enum migrate_mode mode)
|
||||
{
|
||||
return __buffer_migrate_page(mapping, newpage, page, mode, true);
|
||||
return __buffer_migrate_folio(mapping, dst, src, mode, true);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user