fs: Convert aops->write_begin to take a folio

Convert all callers from working on a page to working on one page
of a folio (support for working on an entire folio can come later).
Removes a lot of folio->page->folio conversions.

Reviewed-by: Josef Bacik <josef@toxicpanda.com>
Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
Signed-off-by: Christian Brauner <brauner@kernel.org>
This commit is contained in:
Matthew Wilcox (Oracle)
2024-07-15 14:24:01 -04:00
committed by Christian Brauner
parent a225800f32
commit 1da86618bd
58 changed files with 190 additions and 207 deletions

View File

@@ -251,7 +251,7 @@ prototypes::
void (*readahead)(struct readahead_control *);
int (*write_begin)(struct file *, struct address_space *mapping,
loff_t pos, unsigned len,
struct page **pagep, void **fsdata);
struct folio **foliop, void **fsdata);
int (*write_end)(struct file *, struct address_space *mapping,
loff_t pos, unsigned len, unsigned copied,
struct folio *folio, void *fsdata);
@@ -280,7 +280,7 @@ read_folio: yes, unlocks shared
writepages:
dirty_folio: maybe
readahead: yes, unlocks shared
write_begin: locks the page exclusive
write_begin: locks the folio exclusive
write_end: yes, unlocks exclusive
bmap:
invalidate_folio: yes exclusive

View File

@@ -926,12 +926,12 @@ cache in your filesystem. The following members are defined:
(if they haven't been read already) so that the updated blocks
can be written out properly.
The filesystem must return the locked pagecache page for the
specified offset, in ``*pagep``, for the caller to write into.
The filesystem must return the locked pagecache folio for the
specified offset, in ``*foliop``, for the caller to write into.
It must be able to cope with short writes (where the length
passed to write_begin is greater than the number of bytes copied
into the page).
into the folio).
A void * may be returned in fsdata, which then gets passed into
write_end.

View File

@@ -451,9 +451,9 @@ static void blkdev_readahead(struct readahead_control *rac)
}
static int blkdev_write_begin(struct file *file, struct address_space *mapping,
loff_t pos, unsigned len, struct page **pagep, void **fsdata)
loff_t pos, unsigned len, struct folio **foliop, void **fsdata)
{
return block_write_begin(mapping, pos, len, pagep, blkdev_get_block);
return block_write_begin(mapping, pos, len, foliop, blkdev_get_block);
}
static int blkdev_write_end(struct file *file, struct address_space *mapping,

View File

@@ -424,7 +424,8 @@ shmem_pwrite(struct drm_i915_gem_object *obj,
struct address_space *mapping = obj->base.filp->f_mapping;
const struct address_space_operations *aops = mapping->a_ops;
char __user *user_data = u64_to_user_ptr(arg->data_ptr);
u64 remain, offset;
u64 remain;
loff_t pos;
unsigned int pg;
/* Caller already validated user args */
@@ -457,12 +458,12 @@ shmem_pwrite(struct drm_i915_gem_object *obj,
*/
remain = arg->size;
offset = arg->offset;
pg = offset_in_page(offset);
pos = arg->offset;
pg = offset_in_page(pos);
do {
unsigned int len, unwritten;
struct page *page;
struct folio *folio;
void *data, *vaddr;
int err;
char __maybe_unused c;
@@ -480,21 +481,19 @@ shmem_pwrite(struct drm_i915_gem_object *obj,
if (err)
return err;
err = aops->write_begin(obj->base.filp, mapping, offset, len,
&page, &data);
err = aops->write_begin(obj->base.filp, mapping, pos, len,
&folio, &data);
if (err < 0)
return err;
vaddr = kmap_local_page(page);
vaddr = kmap_local_folio(folio, offset_in_folio(folio, pos));
pagefault_disable();
unwritten = __copy_from_user_inatomic(vaddr + pg,
user_data,
len);
unwritten = __copy_from_user_inatomic(vaddr, user_data, len);
pagefault_enable();
kunmap_local(vaddr);
err = aops->write_end(obj->base.filp, mapping, offset, len,
len - unwritten, page_folio(page), data);
err = aops->write_end(obj->base.filp, mapping, pos, len,
len - unwritten, folio, data);
if (err < 0)
return err;
@@ -504,7 +503,7 @@ shmem_pwrite(struct drm_i915_gem_object *obj,
remain -= len;
user_data += len;
offset += len;
pos += len;
pg = 0;
} while (remain);
@@ -660,7 +659,7 @@ i915_gem_object_create_shmem_from_data(struct drm_i915_private *i915,
struct drm_i915_gem_object *obj;
struct file *file;
const struct address_space_operations *aops;
resource_size_t offset;
loff_t pos;
int err;
GEM_WARN_ON(IS_DGFX(i915));
@@ -672,29 +671,27 @@ i915_gem_object_create_shmem_from_data(struct drm_i915_private *i915,
file = obj->base.filp;
aops = file->f_mapping->a_ops;
offset = 0;
pos = 0;
do {
unsigned int len = min_t(typeof(size), size, PAGE_SIZE);
struct page *page;
void *pgdata, *vaddr;
struct folio *folio;
void *fsdata;
err = aops->write_begin(file, file->f_mapping, offset, len,
&page, &pgdata);
err = aops->write_begin(file, file->f_mapping, pos, len,
&folio, &fsdata);
if (err < 0)
goto fail;
vaddr = kmap(page);
memcpy(vaddr, data, len);
kunmap(page);
memcpy_to_folio(folio, offset_in_folio(folio, pos), data, len);
err = aops->write_end(file, file->f_mapping, offset, len, len,
page_folio(page), pgdata);
err = aops->write_end(file, file->f_mapping, pos, len, len,
folio, fsdata);
if (err < 0)
goto fail;
size -= len;
data += len;
offset += len;
pos += len;
} while (size);
return obj;

View File

@@ -55,12 +55,11 @@ static void adfs_write_failed(struct address_space *mapping, loff_t to)
static int adfs_write_begin(struct file *file, struct address_space *mapping,
loff_t pos, unsigned len,
struct page **pagep, void **fsdata)
struct folio **foliop, void **fsdata)
{
int ret;
*pagep = NULL;
ret = cont_write_begin(file, mapping, pos, len, pagep, fsdata,
ret = cont_write_begin(file, mapping, pos, len, foliop, fsdata,
adfs_get_block,
&ADFS_I(mapping->host)->mmu_private);
if (unlikely(ret))

View File

@@ -417,12 +417,11 @@ affs_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
static int affs_write_begin(struct file *file, struct address_space *mapping,
loff_t pos, unsigned len,
struct page **pagep, void **fsdata)
struct folio **foliop, void **fsdata)
{
int ret;
*pagep = NULL;
ret = cont_write_begin(file, mapping, pos, len, pagep, fsdata,
ret = cont_write_begin(file, mapping, pos, len, foliop, fsdata,
affs_get_block,
&AFFS_I(mapping->host)->mmu_private);
if (unlikely(ret))
@@ -648,7 +647,7 @@ static int affs_read_folio_ofs(struct file *file, struct folio *folio)
static int affs_write_begin_ofs(struct file *file, struct address_space *mapping,
loff_t pos, unsigned len,
struct page **pagep, void **fsdata)
struct folio **foliop, void **fsdata)
{
struct inode *inode = mapping->host;
struct folio *folio;
@@ -671,7 +670,7 @@ static int affs_write_begin_ofs(struct file *file, struct address_space *mapping
mapping_gfp_mask(mapping));
if (IS_ERR(folio))
return PTR_ERR(folio);
*pagep = &folio->page;
*foliop = folio;
if (folio_test_uptodate(folio))
return 0;
@@ -881,14 +880,14 @@ affs_truncate(struct inode *inode)
if (inode->i_size > AFFS_I(inode)->mmu_private) {
struct address_space *mapping = inode->i_mapping;
struct page *page;
struct folio *folio;
void *fsdata = NULL;
loff_t isize = inode->i_size;
int res;
res = mapping->a_ops->write_begin(NULL, mapping, isize, 0, &page, &fsdata);
res = mapping->a_ops->write_begin(NULL, mapping, isize, 0, &folio, &fsdata);
if (!res)
res = mapping->a_ops->write_end(NULL, mapping, isize, 0, 0, page_folio(page), fsdata);
res = mapping->a_ops->write_end(NULL, mapping, isize, 0, 0, folio, fsdata);
else
inode->i_size = AFFS_I(inode)->mmu_private;
mark_inode_dirty(inode);

View File

@@ -659,7 +659,7 @@ int bch2_writepages(struct address_space *mapping, struct writeback_control *wbc
int bch2_write_begin(struct file *file, struct address_space *mapping,
loff_t pos, unsigned len,
struct page **pagep, void **fsdata)
struct folio **foliop, void **fsdata)
{
struct bch_inode_info *inode = to_bch_ei(mapping->host);
struct bch_fs *c = inode->v.i_sb->s_fs_info;
@@ -728,12 +728,11 @@ out:
goto err;
}
*pagep = &folio->page;
*foliop = folio;
return 0;
err:
folio_unlock(folio);
folio_put(folio);
*pagep = NULL;
err_unlock:
bch2_pagecache_add_put(inode);
kfree(res);

View File

@@ -10,8 +10,8 @@ int bch2_read_folio(struct file *, struct folio *);
int bch2_writepages(struct address_space *, struct writeback_control *);
void bch2_readahead(struct readahead_control *);
int bch2_write_begin(struct file *, struct address_space *, loff_t,
unsigned, struct page **, void **);
int bch2_write_begin(struct file *, struct address_space *, loff_t pos,
unsigned len, struct folio **, void **);
int bch2_write_end(struct file *, struct address_space *, loff_t,
unsigned len, unsigned copied, struct folio *, void *);

View File

@@ -172,11 +172,11 @@ static void bfs_write_failed(struct address_space *mapping, loff_t to)
static int bfs_write_begin(struct file *file, struct address_space *mapping,
loff_t pos, unsigned len,
struct page **pagep, void **fsdata)
struct folio **foliop, void **fsdata)
{
int ret;
ret = block_write_begin(mapping, pos, len, pagep, bfs_get_block);
ret = block_write_begin(mapping, pos, len, foliop, bfs_get_block);
if (unlikely(ret))
bfs_write_failed(mapping, pos + len);

View File

@@ -2222,7 +2222,7 @@ static void __block_commit_write(struct folio *folio, size_t from, size_t to)
* The filesystem needs to handle block truncation upon failure.
*/
int block_write_begin(struct address_space *mapping, loff_t pos, unsigned len,
struct page **pagep, get_block_t *get_block)
struct folio **foliop, get_block_t *get_block)
{
pgoff_t index = pos >> PAGE_SHIFT;
struct folio *folio;
@@ -2240,7 +2240,7 @@ int block_write_begin(struct address_space *mapping, loff_t pos, unsigned len,
folio = NULL;
}
*pagep = &folio->page;
*foliop = folio;
return status;
}
EXPORT_SYMBOL(block_write_begin);
@@ -2467,7 +2467,7 @@ int generic_cont_expand_simple(struct inode *inode, loff_t size)
{
struct address_space *mapping = inode->i_mapping;
const struct address_space_operations *aops = mapping->a_ops;
struct page *page;
struct folio *folio;
void *fsdata = NULL;
int err;
@@ -2475,11 +2475,11 @@ int generic_cont_expand_simple(struct inode *inode, loff_t size)
if (err)
goto out;
err = aops->write_begin(NULL, mapping, size, 0, &page, &fsdata);
err = aops->write_begin(NULL, mapping, size, 0, &folio, &fsdata);
if (err)
goto out;
err = aops->write_end(NULL, mapping, size, 0, 0, page_folio(page), fsdata);
err = aops->write_end(NULL, mapping, size, 0, 0, folio, fsdata);
BUG_ON(err > 0);
out:
@@ -2493,7 +2493,7 @@ static int cont_expand_zero(struct file *file, struct address_space *mapping,
struct inode *inode = mapping->host;
const struct address_space_operations *aops = mapping->a_ops;
unsigned int blocksize = i_blocksize(inode);
struct page *page;
struct folio *folio;
void *fsdata = NULL;
pgoff_t index, curidx;
loff_t curpos;
@@ -2512,12 +2512,12 @@ static int cont_expand_zero(struct file *file, struct address_space *mapping,
len = PAGE_SIZE - zerofrom;
err = aops->write_begin(file, mapping, curpos, len,
&page, &fsdata);
&folio, &fsdata);
if (err)
goto out;
zero_user(page, zerofrom, len);
folio_zero_range(folio, offset_in_folio(folio, curpos), len);
err = aops->write_end(file, mapping, curpos, len, len,
page_folio(page), fsdata);
folio, fsdata);
if (err < 0)
goto out;
BUG_ON(err != len);
@@ -2545,12 +2545,12 @@ static int cont_expand_zero(struct file *file, struct address_space *mapping,
len = offset - zerofrom;
err = aops->write_begin(file, mapping, curpos, len,
&page, &fsdata);
&folio, &fsdata);
if (err)
goto out;
zero_user(page, zerofrom, len);
folio_zero_range(folio, offset_in_folio(folio, curpos), len);
err = aops->write_end(file, mapping, curpos, len, len,
page_folio(page), fsdata);
folio, fsdata);
if (err < 0)
goto out;
BUG_ON(err != len);
@@ -2566,7 +2566,7 @@ out:
*/
int cont_write_begin(struct file *file, struct address_space *mapping,
loff_t pos, unsigned len,
struct page **pagep, void **fsdata,
struct folio **foliop, void **fsdata,
get_block_t *get_block, loff_t *bytes)
{
struct inode *inode = mapping->host;
@@ -2584,7 +2584,7 @@ int cont_write_begin(struct file *file, struct address_space *mapping,
(*bytes)++;
}
return block_write_begin(mapping, pos, len, pagep, get_block);
return block_write_begin(mapping, pos, len, foliop, get_block);
}
EXPORT_SYMBOL(cont_write_begin);

View File

@@ -1486,20 +1486,18 @@ static int ceph_netfs_check_write_begin(struct file *file, loff_t pos, unsigned
*/
static int ceph_write_begin(struct file *file, struct address_space *mapping,
loff_t pos, unsigned len,
struct page **pagep, void **fsdata)
struct folio **foliop, void **fsdata)
{
struct inode *inode = file_inode(file);
struct ceph_inode_info *ci = ceph_inode(inode);
struct folio *folio = NULL;
int r;
r = netfs_write_begin(&ci->netfs, file, inode->i_mapping, pos, len, &folio, NULL);
r = netfs_write_begin(&ci->netfs, file, inode->i_mapping, pos, len, foliop, NULL);
if (r < 0)
return r;
folio_wait_private_2(folio); /* [DEPRECATED] */
WARN_ON_ONCE(!folio_test_locked(folio));
*pagep = &folio->page;
folio_wait_private_2(*foliop); /* [DEPRECATED] */
WARN_ON_ONCE(!folio_test_locked(*foliop));
return 0;
}

View File

@@ -255,7 +255,7 @@ out:
* @mapping: The eCryptfs object
* @pos: The file offset at which to start writing
* @len: Length of the write
* @pagep: Pointer to return the page
* @foliop: Pointer to return the folio
* @fsdata: Pointer to return fs data (unused)
*
* This function must zero any hole we create
@@ -265,7 +265,7 @@ out:
static int ecryptfs_write_begin(struct file *file,
struct address_space *mapping,
loff_t pos, unsigned len,
struct page **pagep, void **fsdata)
struct folio **foliop, void **fsdata)
{
pgoff_t index = pos >> PAGE_SHIFT;
struct folio *folio;
@@ -276,7 +276,7 @@ static int ecryptfs_write_begin(struct file *file,
mapping_gfp_mask(mapping));
if (IS_ERR(folio))
return PTR_ERR(folio);
*pagep = &folio->page;
*foliop = folio;
prev_page_end_size = ((loff_t)index << PAGE_SHIFT);
if (!folio_test_uptodate(folio)) {
@@ -365,7 +365,6 @@ out:
if (unlikely(rc)) {
folio_unlock(folio);
folio_put(folio);
*pagep = NULL;
}
return rc;
}

View File

@@ -535,20 +535,20 @@ static int exfat_file_zeroed_range(struct file *file, loff_t start, loff_t end)
while (start < end) {
u32 zerofrom, len;
struct page *page = NULL;
struct folio *folio;
zerofrom = start & (PAGE_SIZE - 1);
len = PAGE_SIZE - zerofrom;
if (start + len > end)
len = end - start;
err = ops->write_begin(file, mapping, start, len, &page, NULL);
err = ops->write_begin(file, mapping, start, len, &folio, NULL);
if (err)
goto out;
zero_user_segment(page, zerofrom, zerofrom + len);
folio_zero_range(folio, offset_in_folio(folio, start), len);
err = ops->write_end(file, mapping, start, len, len, page_folio(page), NULL);
err = ops->write_end(file, mapping, start, len, len, folio, NULL);
if (err < 0)
goto out;
start += len;

View File

@@ -448,12 +448,11 @@ static void exfat_write_failed(struct address_space *mapping, loff_t to)
static int exfat_write_begin(struct file *file, struct address_space *mapping,
loff_t pos, unsigned int len,
struct page **pagep, void **fsdata)
struct folio **foliop, void **fsdata)
{
int ret;
*pagep = NULL;
ret = block_write_begin(mapping, pos, len, pagep, exfat_get_block);
ret = block_write_begin(mapping, pos, len, foliop, exfat_get_block);
if (ret < 0)
exfat_write_failed(mapping, pos+len);

View File

@@ -916,11 +916,11 @@ static void ext2_readahead(struct readahead_control *rac)
static int
ext2_write_begin(struct file *file, struct address_space *mapping,
loff_t pos, unsigned len, struct page **pagep, void **fsdata)
loff_t pos, unsigned len, struct folio **foliop, void **fsdata)
{
int ret;
ret = block_write_begin(mapping, pos, len, pagep, ext2_get_block);
ret = block_write_begin(mapping, pos, len, foliop, ext2_get_block);
if (ret < 0)
ext2_write_failed(mapping, pos + len);
return ret;

View File

@@ -3563,13 +3563,13 @@ int ext4_readpage_inline(struct inode *inode, struct folio *folio);
extern int ext4_try_to_write_inline_data(struct address_space *mapping,
struct inode *inode,
loff_t pos, unsigned len,
struct page **pagep);
struct folio **foliop);
int ext4_write_inline_data_end(struct inode *inode, loff_t pos, unsigned len,
unsigned copied, struct folio *folio);
extern int ext4_da_write_inline_data_begin(struct address_space *mapping,
struct inode *inode,
loff_t pos, unsigned len,
struct page **pagep,
struct folio **foliop,
void **fsdata);
extern int ext4_try_add_inline_entry(handle_t *handle,
struct ext4_filename *fname,

View File

@@ -660,7 +660,7 @@ out_nofolio:
int ext4_try_to_write_inline_data(struct address_space *mapping,
struct inode *inode,
loff_t pos, unsigned len,
struct page **pagep)
struct folio **foliop)
{
int ret;
handle_t *handle;
@@ -708,7 +708,7 @@ int ext4_try_to_write_inline_data(struct address_space *mapping,
goto out;
}
*pagep = &folio->page;
*foliop = folio;
down_read(&EXT4_I(inode)->xattr_sem);
if (!ext4_has_inline_data(inode)) {
ret = 0;
@@ -891,7 +891,7 @@ out:
int ext4_da_write_inline_data_begin(struct address_space *mapping,
struct inode *inode,
loff_t pos, unsigned len,
struct page **pagep,
struct folio **foliop,
void **fsdata)
{
int ret;
@@ -954,7 +954,7 @@ retry_journal:
goto out_release_page;
up_read(&EXT4_I(inode)->xattr_sem);
*pagep = &folio->page;
*foliop = folio;
brelse(iloc.bh);
return 1;
out_release_page:

View File

@@ -1145,7 +1145,7 @@ static int ext4_block_write_begin(struct folio *folio, loff_t pos, unsigned len,
*/
static int ext4_write_begin(struct file *file, struct address_space *mapping,
loff_t pos, unsigned len,
struct page **pagep, void **fsdata)
struct folio **foliop, void **fsdata)
{
struct inode *inode = mapping->host;
int ret, needed_blocks;
@@ -1170,7 +1170,7 @@ static int ext4_write_begin(struct file *file, struct address_space *mapping,
if (ext4_test_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA)) {
ret = ext4_try_to_write_inline_data(mapping, inode, pos, len,
pagep);
foliop);
if (ret < 0)
return ret;
if (ret == 1)
@@ -1270,7 +1270,7 @@ retry_journal:
folio_put(folio);
return ret;
}
*pagep = &folio->page;
*foliop = folio;
return ret;
}
@@ -2924,7 +2924,7 @@ static int ext4_nonda_switch(struct super_block *sb)
static int ext4_da_write_begin(struct file *file, struct address_space *mapping,
loff_t pos, unsigned len,
struct page **pagep, void **fsdata)
struct folio **foliop, void **fsdata)
{
int ret, retries = 0;
struct folio *folio;
@@ -2939,14 +2939,14 @@ static int ext4_da_write_begin(struct file *file, struct address_space *mapping,
if (ext4_nonda_switch(inode->i_sb) || ext4_verity_in_progress(inode)) {
*fsdata = (void *)FALL_BACK_TO_NONDELALLOC;
return ext4_write_begin(file, mapping, pos,
len, pagep, fsdata);
len, foliop, fsdata);
}
*fsdata = (void *)0;
trace_ext4_da_write_begin(inode, pos, len);
if (ext4_test_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA)) {
ret = ext4_da_write_inline_data_begin(mapping, inode, pos, len,
pagep, fsdata);
foliop, fsdata);
if (ret < 0)
return ret;
if (ret == 1)
@@ -2981,7 +2981,7 @@ retry:
return ret;
}
*pagep = &folio->page;
*foliop = folio;
return ret;
}

View File

@@ -76,17 +76,17 @@ static int pagecache_write(struct inode *inode, const void *buf, size_t count,
while (count) {
size_t n = min_t(size_t, count,
PAGE_SIZE - offset_in_page(pos));
struct page *page;
struct folio *folio;
void *fsdata = NULL;
int res;
res = aops->write_begin(NULL, mapping, pos, n, &page, &fsdata);
res = aops->write_begin(NULL, mapping, pos, n, &folio, &fsdata);
if (res)
return res;
memcpy_to_page(page, offset_in_page(pos), buf, n);
memcpy_to_folio(folio, offset_in_folio(folio, pos), buf, n);
res = aops->write_end(NULL, mapping, pos, n, n, page_folio(page), fsdata);
res = aops->write_end(NULL, mapping, pos, n, n, folio, fsdata);
if (res < 0)
return res;
if (res != n)

View File

@@ -3552,7 +3552,7 @@ reserve_block:
}
static int f2fs_write_begin(struct file *file, struct address_space *mapping,
loff_t pos, unsigned len, struct page **pagep, void **fsdata)
loff_t pos, unsigned len, struct folio **foliop, void **fsdata)
{
struct inode *inode = mapping->host;
struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
@@ -3584,18 +3584,20 @@ static int f2fs_write_begin(struct file *file, struct address_space *mapping,
#ifdef CONFIG_F2FS_FS_COMPRESSION
if (f2fs_compressed_file(inode)) {
int ret;
struct page *page;
*fsdata = NULL;
if (len == PAGE_SIZE && !(f2fs_is_atomic_file(inode)))
goto repeat;
ret = f2fs_prepare_compress_overwrite(inode, pagep,
ret = f2fs_prepare_compress_overwrite(inode, &page,
index, fsdata);
if (ret < 0) {
err = ret;
goto fail;
} else if (ret) {
*foliop = page_folio(page);
return 0;
}
}
@@ -3615,7 +3617,7 @@ repeat:
/* TODO: cluster can be compressed due to race with .writepage */
*pagep = &folio->page;
*foliop = folio;
if (f2fs_is_atomic_file(inode))
err = prepare_atomic_write_begin(sbi, &folio->page, pos, len,

Some files were not shown because too many files have changed in this diff Show More