mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-11 12:28:41 +08:00
nilfs2: localize highmem mapping for checkpoint finalization within cpfile
Move the checkpoint finalization routine to the cpfile side, and make the page mapping local and temporary. And use kmap_local instead of kmap to access the checkpoint entry page when finalizing a checkpoint. In this conversion, some of the information on the checkpoint entry being rewritten is passed through the arguments of the newly added method nilfs_cpfile_finalize_checkpoint(). Link: https://lkml.kernel.org/r/20240122140202.6950-13-konishi.ryusuke@gmail.com Signed-off-by: Ryusuke Konishi <konishi.ryusuke@gmail.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
This commit is contained in:
parent
d37db936c5
commit
cce259b4c3
@ -363,6 +363,80 @@ void nilfs_cpfile_put_checkpoint(struct inode *cpfile, __u64 cno,
|
||||
brelse(bh);
|
||||
}
|
||||
|
||||
/**
|
||||
* nilfs_cpfile_finalize_checkpoint - fill in a checkpoint entry in cpfile
|
||||
* @cpfile: checkpoint file inode
|
||||
* @cno: checkpoint number
|
||||
* @root: nilfs root object
|
||||
* @blkinc: number of blocks added by this checkpoint
|
||||
* @ctime: checkpoint creation time
|
||||
* @minor: minor checkpoint flag
|
||||
*
|
||||
* This function completes the checkpoint entry numbered by @cno in the
|
||||
* cpfile with the data given by the arguments @root, @blkinc, @ctime, and
|
||||
* @minor.
|
||||
*
|
||||
* Return: 0 on success, or the following negative error code on failure.
|
||||
* * %-ENOMEM - Insufficient memory available.
|
||||
* * %-EIO - I/O error (including metadata corruption).
|
||||
*/
|
||||
int nilfs_cpfile_finalize_checkpoint(struct inode *cpfile, __u64 cno,
|
||||
struct nilfs_root *root, __u64 blkinc,
|
||||
time64_t ctime, bool minor)
|
||||
{
|
||||
struct buffer_head *cp_bh;
|
||||
struct nilfs_checkpoint *cp;
|
||||
void *kaddr;
|
||||
int ret;
|
||||
|
||||
if (WARN_ON_ONCE(cno < 1))
|
||||
return -EIO;
|
||||
|
||||
down_write(&NILFS_MDT(cpfile)->mi_sem);
|
||||
ret = nilfs_cpfile_get_checkpoint_block(cpfile, cno, 0, &cp_bh);
|
||||
if (unlikely(ret < 0)) {
|
||||
if (ret == -ENOENT)
|
||||
goto error;
|
||||
goto out_sem;
|
||||
}
|
||||
|
||||
kaddr = kmap_local_page(cp_bh->b_page);
|
||||
cp = nilfs_cpfile_block_get_checkpoint(cpfile, cno, cp_bh, kaddr);
|
||||
if (unlikely(nilfs_checkpoint_invalid(cp))) {
|
||||
kunmap_local(kaddr);
|
||||
brelse(cp_bh);
|
||||
goto error;
|
||||
}
|
||||
|
||||
cp->cp_snapshot_list.ssl_next = 0;
|
||||
cp->cp_snapshot_list.ssl_prev = 0;
|
||||
cp->cp_inodes_count = cpu_to_le64(atomic64_read(&root->inodes_count));
|
||||
cp->cp_blocks_count = cpu_to_le64(atomic64_read(&root->blocks_count));
|
||||
cp->cp_nblk_inc = cpu_to_le64(blkinc);
|
||||
cp->cp_create = cpu_to_le64(ctime);
|
||||
cp->cp_cno = cpu_to_le64(cno);
|
||||
|
||||
if (minor)
|
||||
nilfs_checkpoint_set_minor(cp);
|
||||
else
|
||||
nilfs_checkpoint_clear_minor(cp);
|
||||
|
||||
nilfs_write_inode_common(root->ifile, &cp->cp_ifile_inode);
|
||||
nilfs_bmap_write(NILFS_I(root->ifile)->i_bmap, &cp->cp_ifile_inode);
|
||||
|
||||
kunmap_local(kaddr);
|
||||
brelse(cp_bh);
|
||||
out_sem:
|
||||
up_write(&NILFS_MDT(cpfile)->mi_sem);
|
||||
return ret;
|
||||
|
||||
error:
|
||||
nilfs_error(cpfile->i_sb,
|
||||
"checkpoint finalization failed due to metadata corruption.");
|
||||
ret = -EIO;
|
||||
goto out_sem;
|
||||
}
|
||||
|
||||
/**
|
||||
* nilfs_cpfile_delete_checkpoints - delete checkpoints
|
||||
* @cpfile: inode of checkpoint file
|
||||
|
@ -21,6 +21,9 @@ int nilfs_cpfile_get_checkpoint(struct inode *, __u64, int,
|
||||
struct buffer_head **);
|
||||
int nilfs_cpfile_create_checkpoint(struct inode *cpfile, __u64 cno);
|
||||
void nilfs_cpfile_put_checkpoint(struct inode *, __u64, struct buffer_head *);
|
||||
int nilfs_cpfile_finalize_checkpoint(struct inode *cpfile, __u64 cno,
|
||||
struct nilfs_root *root, __u64 blkinc,
|
||||
time64_t ctime, bool minor);
|
||||
int nilfs_cpfile_delete_checkpoints(struct inode *, __u64, __u64);
|
||||
int nilfs_cpfile_delete_checkpoint(struct inode *, __u64);
|
||||
int nilfs_cpfile_change_cpmode(struct inode *, __u64, int);
|
||||
|
@ -880,51 +880,6 @@ static void nilfs_segctor_clear_metadata_dirty(struct nilfs_sc_info *sci)
|
||||
nilfs_mdt_clear_dirty(nilfs->ns_dat);
|
||||
}
|
||||
|
||||
static int nilfs_segctor_fill_in_checkpoint(struct nilfs_sc_info *sci)
|
||||
{
|
||||
struct the_nilfs *nilfs = sci->sc_super->s_fs_info;
|
||||
struct buffer_head *bh_cp;
|
||||
struct nilfs_checkpoint *raw_cp;
|
||||
struct inode *ifile;
|
||||
int err;
|
||||
|
||||
err = nilfs_cpfile_get_checkpoint(nilfs->ns_cpfile, nilfs->ns_cno, 0,
|
||||
&raw_cp, &bh_cp);
|
||||
if (unlikely(err)) {
|
||||
if (err == -EINVAL || err == -ENOENT) {
|
||||
nilfs_error(sci->sc_super,
|
||||
"checkpoint finalization failed due to metadata corruption.");
|
||||
err = -EIO;
|
||||
}
|
||||
goto failed_ibh;
|
||||
}
|
||||
raw_cp->cp_snapshot_list.ssl_next = 0;
|
||||
raw_cp->cp_snapshot_list.ssl_prev = 0;
|
||||
raw_cp->cp_inodes_count =
|
||||
cpu_to_le64(atomic64_read(&sci->sc_root->inodes_count));
|
||||
raw_cp->cp_blocks_count =
|
||||
cpu_to_le64(atomic64_read(&sci->sc_root->blocks_count));
|
||||
raw_cp->cp_nblk_inc =
|
||||
cpu_to_le64(sci->sc_nblk_inc + sci->sc_nblk_this_inc);
|
||||
raw_cp->cp_create = cpu_to_le64(sci->sc_seg_ctime);
|
||||
raw_cp->cp_cno = cpu_to_le64(nilfs->ns_cno);
|
||||
|
||||
if (test_bit(NILFS_SC_HAVE_DELTA, &sci->sc_flags))
|
||||
nilfs_checkpoint_clear_minor(raw_cp);
|
||||
else
|
||||
nilfs_checkpoint_set_minor(raw_cp);
|
||||
|
||||
ifile = sci->sc_root->ifile;
|
||||
nilfs_write_inode_common(ifile, &raw_cp->cp_ifile_inode);
|
||||
nilfs_bmap_write(NILFS_I(ifile)->i_bmap, &raw_cp->cp_ifile_inode);
|
||||
|
||||
nilfs_cpfile_put_checkpoint(nilfs->ns_cpfile, nilfs->ns_cno, bh_cp);
|
||||
return 0;
|
||||
|
||||
failed_ibh:
|
||||
return err;
|
||||
}
|
||||
|
||||
static void nilfs_fill_in_file_bmap(struct inode *ifile,
|
||||
struct nilfs_inode_info *ii)
|
||||
|
||||
@ -2105,7 +2060,11 @@ static int nilfs_segctor_do_construct(struct nilfs_sc_info *sci, int mode)
|
||||
|
||||
if (mode == SC_LSEG_SR &&
|
||||
nilfs_sc_cstage_get(sci) >= NILFS_ST_CPFILE) {
|
||||
err = nilfs_segctor_fill_in_checkpoint(sci);
|
||||
err = nilfs_cpfile_finalize_checkpoint(
|
||||
nilfs->ns_cpfile, nilfs->ns_cno, sci->sc_root,
|
||||
sci->sc_nblk_inc + sci->sc_nblk_this_inc,
|
||||
sci->sc_seg_ctime,
|
||||
!test_bit(NILFS_SC_HAVE_DELTA, &sci->sc_flags));
|
||||
if (unlikely(err))
|
||||
goto failed_to_write;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user