Skip to content

Commit

Permalink
Allow switching of folio-based write_{begin,end}
Browse files Browse the repository at this point in the history
In kernel 6.12-rc1, *_write_begin and *_write_end were converted to
folio-based.

Define wrapper macros so that these functions can be switched
depending on the kernel version, and use these macros.

For RHEL 10 clone kernels, the folio-based functions are applied for
RHEL_RELEASE >= 27.

Signed-off-by: Ryusuke Konishi <konishi.ryusuke@gmail.com>
konis committed Nov 5, 2024
1 parent 3c0c852 commit d527f85
Showing 4 changed files with 68 additions and 15 deletions.
7 changes: 5 additions & 2 deletions fs/nilfs2/dir.c
Original file line number Diff line number Diff line change
@@ -30,6 +30,7 @@
*/

#include <linux/pagemap.h>
#include "kern_feature.h"
#include "nilfs.h"
#include "page.h"

@@ -83,7 +84,8 @@ static int nilfs_prepare_chunk(struct folio *folio, unsigned int from,
{
loff_t pos = folio_pos(folio) + from;

return __block_write_begin(&folio->page, pos, to - from, nilfs_get_block);
return compat___block_write_begin(folio, pos, to - from,
nilfs_get_block);
}

static void nilfs_commit_chunk(struct folio *folio,
@@ -96,7 +98,8 @@ static void nilfs_commit_chunk(struct folio *folio,
int err;

nr_dirty = nilfs_page_count_clean_buffers(&folio->page, from, to);
copied = block_write_end(NULL, mapping, pos, len, len, &folio->page, NULL);
copied = compat_block_write_end(NULL, mapping, pos, len, len, folio,
NULL);
if (pos + copied > dir->i_size)
i_size_write(dir, pos + copied);
if (IS_DIRSYNC(dir))
26 changes: 20 additions & 6 deletions fs/nilfs2/inode.c
Original file line number Diff line number Diff line change
@@ -16,6 +16,7 @@
#include <linux/uio.h>
#include <linux/fiemap.h>
#include <linux/random.h>
#include "kern_feature.h"
#include "nilfs.h"
#include "btnode.h"
#include "segment.h"
@@ -247,16 +248,20 @@ void nilfs_write_failed(struct address_space *mapping, loff_t to)

static int nilfs_write_begin(struct file *file, struct address_space *mapping,
loff_t pos, unsigned len,
struct page **pagep, void **fsdata)

#if HAVE_FOLIO_BASED_WRITE_BEGIN_END
struct folio **p,
#else
struct page **p,
#endif
void **fsdata)
{
struct inode *inode = mapping->host;
int err = nilfs_transaction_begin(inode->i_sb, NULL, 1);

if (unlikely(err))
return err;

err = block_write_begin(mapping, pos, len, pagep, nilfs_get_block);
err = block_write_begin(mapping, pos, len, p, nilfs_get_block);
if (unlikely(err)) {
nilfs_write_failed(mapping, pos + len);
nilfs_transaction_abort(inode->i_sb);
@@ -266,17 +271,26 @@ static int nilfs_write_begin(struct file *file, struct address_space *mapping,

static int nilfs_write_end(struct file *file, struct address_space *mapping,
loff_t pos, unsigned len, unsigned copied,
struct page *page, void *fsdata)
#if HAVE_FOLIO_BASED_WRITE_BEGIN_END
struct folio *p,
#else
struct page *p,
#endif
void *fsdata)
{
struct inode *inode = mapping->host;
#if HAVE_FOLIO_BASED_WRITE_BEGIN_END
struct page *page = &p->page;
#else
struct page *page = p;
#endif
unsigned int start = pos & (PAGE_SIZE - 1);
unsigned int nr_dirty;
int err;

nr_dirty = nilfs_page_count_clean_buffers(page, start,
start + copied);
copied = generic_write_end(file, mapping, pos, len, copied, page,
fsdata);
copied = generic_write_end(file, mapping, pos, len, copied, p, fsdata);
nilfs_set_file_dirty(inode, nr_dirty);
err = nilfs_transaction_commit(inode->i_sb);
return err ? : copied;
37 changes: 37 additions & 0 deletions fs/nilfs2/kern_feature.h
Original file line number Diff line number Diff line change
@@ -20,6 +20,11 @@
*/
#if defined(RHEL_MAJOR) && (RHEL_MAJOR == 10)
# if defined(RHEL_RELEASE_N)
# if (RHEL_RELEASE_N >= 27)
# define HAVE_FOLIO_BASED_WRITE_BEGIN_END 1
# endif
# else /* !defined(RHEL_RELEASE_N) */
# define HAVE_FOLIO_BASED_WRITE_BEGIN_END 1
# endif
#endif

@@ -31,9 +36,41 @@
* defaults dependent to kernel versions
*/
#ifdef LINUX_VERSION_CODE
/*
* write_begin and write_end interfaces were converted to folio-based
* in kernel 6.12-rc1.
*/
#ifndef HAVE_FOLIO_BASED_WRITE_BEGIN_END
# define HAVE_FOLIO_BASED_WRITE_BEGIN_END \
(LINUX_VERSION_CODE >= KERNEL_VERSION(6, 12, 0))
#endif
#endif /* LINUX_VERSION_CODE */


#include <linux/fs.h>

#if HAVE_FOLIO_BASED_WRITE_BEGIN_END
#define compat___block_write_begin(folio, pos, len, get_block) \
__block_write_begin(folio, pos, len, get_block)
#define compat_block_write_begin(mapping, pos, len, foliop, get_block) \
block_write_begin(mapping, pos, len, foliop, get_block)
#define compat_block_write_end(file, mapping, pos, len, copied, folio, data) \
block_write_end(file, mapping, pos, len, copied, folio, data)
#else /* HAVE_FOLIO_BASED_WRITE_BEGIN_END */
#define compat___block_write_begin(folio, pos, len, get_block) \
__block_write_begin(&(folio)->page, pos, len, get_block)
#define compat_block_write_begin(mapping, pos, len, foliop, get_block) \
({ \
struct page *__page; \
int __rc; \
__rc = block_write_begin(mapping, pos, len, &__page, \
get_block); \
if (likely(!__rc)) \
*(foliop) = page_folio(__page); \
__rc; \
})
#define compat_block_write_end(file, mapping, pos, len, copied, folio, data) \
block_write_end(file, mapping, pos, len, copied, &(folio)->page, data)
#endif /* HAVE_FOLIO_BASED_WRITE_BEGIN_END */

#endif /* NILFS_KERN_FEATURE_H */
13 changes: 6 additions & 7 deletions fs/nilfs2/recovery.c
Original file line number Diff line number Diff line change
@@ -12,6 +12,7 @@
#include <linux/swap.h>
#include <linux/slab.h>
#include <linux/crc32.h>
#include "kern_feature.h"
#include "nilfs.h"
#include "segment.h"
#include "sufile.h"
@@ -507,7 +508,6 @@ static int nilfs_recover_dsync_blocks(struct the_nilfs *nilfs,
struct inode *inode;
struct nilfs_recovery_block *rb, *n;
unsigned int blocksize = nilfs->ns_blocksize;
struct page *page;
struct folio *folio;
loff_t pos;
int err = 0, err2 = 0;
@@ -521,8 +521,8 @@ static int nilfs_recover_dsync_blocks(struct the_nilfs *nilfs,
}

pos = rb->blkoff << inode->i_blkbits;
err = block_write_begin(inode->i_mapping, pos, blocksize,
&page, nilfs_get_block);
err = compat_block_write_begin(inode->i_mapping, pos, blocksize,
&folio, nilfs_get_block);
if (unlikely(err)) {
loff_t isize = inode->i_size;

@@ -532,17 +532,16 @@ static int nilfs_recover_dsync_blocks(struct the_nilfs *nilfs,
goto failed_inode;
}

folio = page_folio(page);
err = nilfs_recovery_copy_block(nilfs, rb, pos, page);
err = nilfs_recovery_copy_block(nilfs, rb, pos, &folio->page);
if (unlikely(err))
goto failed_page;

err = nilfs_set_file_dirty(inode, 1);
if (unlikely(err))
goto failed_page;

block_write_end(NULL, inode->i_mapping, pos, blocksize,
blocksize, page, NULL);
compat_block_write_end(NULL, inode->i_mapping, pos, blocksize,
blocksize, folio, NULL);

folio_unlock(folio);
folio_put(folio);

0 comments on commit d527f85

Please sign in to comment.