On Thursday, April 30, 2020 6:18 AM Darrick J. Wong wrote: > From: Darrick J. Wong <darrick.wong@xxxxxxxxxx> > > Move the log icreate item pass2 commit code into the per-item source code > files and use the dispatch function to call it. We do these one at a > time because there's a lot of code to move. No functional changes. > The changes look good to me. Reviewed-by: Chandan Rajendra <chandanrlinux@xxxxxxxxx> > Signed-off-by: Darrick J. Wong <darrick.wong@xxxxxxxxxx> > --- > fs/xfs/xfs_icreate_item.c | 132 +++++++++++++++++++++++++++++++++++++++++++++ > fs/xfs/xfs_log_recover.c | 126 ------------------------------------------- > 2 files changed, 132 insertions(+), 126 deletions(-) > > > diff --git a/fs/xfs/xfs_icreate_item.c b/fs/xfs/xfs_icreate_item.c > index 9f38a3c200a3..602a8c91371f 100644 > --- a/fs/xfs/xfs_icreate_item.c > +++ b/fs/xfs/xfs_icreate_item.c > @@ -6,13 +6,19 @@ > #include "xfs.h" > #include "xfs_fs.h" > #include "xfs_shared.h" > +#include "xfs_format.h" > #include "xfs_log_format.h" > +#include "xfs_trans_resv.h" > +#include "xfs_mount.h" > +#include "xfs_inode.h" > #include "xfs_trans.h" > #include "xfs_trans_priv.h" > #include "xfs_icreate_item.h" > #include "xfs_log.h" > #include "xfs_log_priv.h" > #include "xfs_log_recover.h" > +#include "xfs_ialloc.h" > +#include "xfs_trace.h" > > kmem_zone_t *xfs_icreate_zone; /* inode create item zone */ > > @@ -117,6 +123,132 @@ xlog_icreate_reorder( > return XLOG_REORDER_BUFFER_LIST; > } > > +/* > + * This routine is called when an inode create format structure is found in a > + * committed transaction in the log. It's purpose is to initialise the inodes > + * being allocated on disk. This requires us to get inode cluster buffers that > + * match the range to be initialised, stamped with inode templates and written > + * by delayed write so that subsequent modifications will hit the cached buffer > + * and only need writing out at the end of recovery. > + */ > +STATIC int > +xlog_recover_do_icreate_commit_pass2( > + struct xlog *log, > + struct list_head *buffer_list, > + struct xlog_recover_item *item, > + xfs_lsn_t lsn) > +{ > + struct xfs_mount *mp = log->l_mp; > + struct xfs_icreate_log *icl; > + struct xfs_ino_geometry *igeo = M_IGEO(mp); > + xfs_agnumber_t agno; > + xfs_agblock_t agbno; > + unsigned int count; > + unsigned int isize; > + xfs_agblock_t length; > + int bb_per_cluster; > + int cancel_count; > + int nbufs; > + int i; > + > + icl = (struct xfs_icreate_log *)item->ri_buf[0].i_addr; > + if (icl->icl_type != XFS_LI_ICREATE) { > + xfs_warn(log->l_mp, "xlog_recover_do_icreate_trans: bad type"); > + return -EINVAL; > + } > + > + if (icl->icl_size != 1) { > + xfs_warn(log->l_mp, "xlog_recover_do_icreate_trans: bad icl size"); > + return -EINVAL; > + } > + > + agno = be32_to_cpu(icl->icl_ag); > + if (agno >= mp->m_sb.sb_agcount) { > + xfs_warn(log->l_mp, "xlog_recover_do_icreate_trans: bad agno"); > + return -EINVAL; > + } > + agbno = be32_to_cpu(icl->icl_agbno); > + if (!agbno || agbno == NULLAGBLOCK || agbno >= mp->m_sb.sb_agblocks) { > + xfs_warn(log->l_mp, "xlog_recover_do_icreate_trans: bad agbno"); > + return -EINVAL; > + } > + isize = be32_to_cpu(icl->icl_isize); > + if (isize != mp->m_sb.sb_inodesize) { > + xfs_warn(log->l_mp, "xlog_recover_do_icreate_trans: bad isize"); > + return -EINVAL; > + } > + count = be32_to_cpu(icl->icl_count); > + if (!count) { > + xfs_warn(log->l_mp, "xlog_recover_do_icreate_trans: bad count"); > + return -EINVAL; > + } > + length = be32_to_cpu(icl->icl_length); > + if (!length || length >= mp->m_sb.sb_agblocks) { > + xfs_warn(log->l_mp, "xlog_recover_do_icreate_trans: bad length"); > + return -EINVAL; > + } > + > + /* > + * The inode chunk is either full or sparse and we only support > + * m_ino_geo.ialloc_min_blks sized sparse allocations at this time. > + */ > + if (length != igeo->ialloc_blks && > + length != igeo->ialloc_min_blks) { > + xfs_warn(log->l_mp, > + "%s: unsupported chunk length", __FUNCTION__); > + return -EINVAL; > + } > + > + /* verify inode count is consistent with extent length */ > + if ((count >> mp->m_sb.sb_inopblog) != length) { > + xfs_warn(log->l_mp, > + "%s: inconsistent inode count and chunk length", > + __FUNCTION__); > + return -EINVAL; > + } > + > + /* > + * The icreate transaction can cover multiple cluster buffers and these > + * buffers could have been freed and reused. Check the individual > + * buffers for cancellation so we don't overwrite anything written after > + * a cancellation. > + */ > + bb_per_cluster = XFS_FSB_TO_BB(mp, igeo->blocks_per_cluster); > + nbufs = length / igeo->blocks_per_cluster; > + for (i = 0, cancel_count = 0; i < nbufs; i++) { > + xfs_daddr_t daddr; > + > + daddr = XFS_AGB_TO_DADDR(mp, agno, > + agbno + i * igeo->blocks_per_cluster); > + if (xlog_is_buffer_cancelled(log, daddr, bb_per_cluster)) > + cancel_count++; > + } > + > + /* > + * We currently only use icreate for a single allocation at a time. This > + * means we should expect either all or none of the buffers to be > + * cancelled. Be conservative and skip replay if at least one buffer is > + * cancelled, but warn the user that something is awry if the buffers > + * are not consistent. > + * > + * XXX: This must be refined to only skip cancelled clusters once we use > + * icreate for multiple chunk allocations. > + */ > + ASSERT(!cancel_count || cancel_count == nbufs); > + if (cancel_count) { > + if (cancel_count != nbufs) > + xfs_warn(mp, > + "WARNING: partial inode chunk cancellation, skipped icreate."); > + trace_xfs_log_recover_icreate_cancel(log, icl); > + return 0; > + } > + > + trace_xfs_log_recover_icreate_recover(log, icl); > + return xfs_ialloc_inode_init(mp, NULL, buffer_list, count, agno, agbno, > + length, be32_to_cpu(icl->icl_gen)); > +} > + > const struct xlog_recover_item_type xlog_icreate_item_type = { > .reorder_fn = xlog_icreate_reorder, > + .commit_pass2_fn = xlog_recover_do_icreate_commit_pass2, > }; > diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c > index 58a54d9e6847..6ba3d64d08de 100644 > --- a/fs/xfs/xfs_log_recover.c > +++ b/fs/xfs/xfs_log_recover.c > @@ -2489,130 +2489,6 @@ xlog_recover_bud_pass2( > return 0; > } > > -/* > - * This routine is called when an inode create format structure is found in a > - * committed transaction in the log. It's purpose is to initialise the inodes > - * being allocated on disk. This requires us to get inode cluster buffers that > - * match the range to be initialised, stamped with inode templates and written > - * by delayed write so that subsequent modifications will hit the cached buffer > - * and only need writing out at the end of recovery. > - */ > -STATIC int > -xlog_recover_do_icreate_pass2( > - struct xlog *log, > - struct list_head *buffer_list, > - xlog_recover_item_t *item) > -{ > - struct xfs_mount *mp = log->l_mp; > - struct xfs_icreate_log *icl; > - struct xfs_ino_geometry *igeo = M_IGEO(mp); > - xfs_agnumber_t agno; > - xfs_agblock_t agbno; > - unsigned int count; > - unsigned int isize; > - xfs_agblock_t length; > - int bb_per_cluster; > - int cancel_count; > - int nbufs; > - int i; > - > - icl = (struct xfs_icreate_log *)item->ri_buf[0].i_addr; > - if (icl->icl_type != XFS_LI_ICREATE) { > - xfs_warn(log->l_mp, "xlog_recover_do_icreate_trans: bad type"); > - return -EINVAL; > - } > - > - if (icl->icl_size != 1) { > - xfs_warn(log->l_mp, "xlog_recover_do_icreate_trans: bad icl size"); > - return -EINVAL; > - } > - > - agno = be32_to_cpu(icl->icl_ag); > - if (agno >= mp->m_sb.sb_agcount) { > - xfs_warn(log->l_mp, "xlog_recover_do_icreate_trans: bad agno"); > - return -EINVAL; > - } > - agbno = be32_to_cpu(icl->icl_agbno); > - if (!agbno || agbno == NULLAGBLOCK || agbno >= mp->m_sb.sb_agblocks) { > - xfs_warn(log->l_mp, "xlog_recover_do_icreate_trans: bad agbno"); > - return -EINVAL; > - } > - isize = be32_to_cpu(icl->icl_isize); > - if (isize != mp->m_sb.sb_inodesize) { > - xfs_warn(log->l_mp, "xlog_recover_do_icreate_trans: bad isize"); > - return -EINVAL; > - } > - count = be32_to_cpu(icl->icl_count); > - if (!count) { > - xfs_warn(log->l_mp, "xlog_recover_do_icreate_trans: bad count"); > - return -EINVAL; > - } > - length = be32_to_cpu(icl->icl_length); > - if (!length || length >= mp->m_sb.sb_agblocks) { > - xfs_warn(log->l_mp, "xlog_recover_do_icreate_trans: bad length"); > - return -EINVAL; > - } > - > - /* > - * The inode chunk is either full or sparse and we only support > - * m_ino_geo.ialloc_min_blks sized sparse allocations at this time. > - */ > - if (length != igeo->ialloc_blks && > - length != igeo->ialloc_min_blks) { > - xfs_warn(log->l_mp, > - "%s: unsupported chunk length", __FUNCTION__); > - return -EINVAL; > - } > - > - /* verify inode count is consistent with extent length */ > - if ((count >> mp->m_sb.sb_inopblog) != length) { > - xfs_warn(log->l_mp, > - "%s: inconsistent inode count and chunk length", > - __FUNCTION__); > - return -EINVAL; > - } > - > - /* > - * The icreate transaction can cover multiple cluster buffers and these > - * buffers could have been freed and reused. Check the individual > - * buffers for cancellation so we don't overwrite anything written after > - * a cancellation. > - */ > - bb_per_cluster = XFS_FSB_TO_BB(mp, igeo->blocks_per_cluster); > - nbufs = length / igeo->blocks_per_cluster; > - for (i = 0, cancel_count = 0; i < nbufs; i++) { > - xfs_daddr_t daddr; > - > - daddr = XFS_AGB_TO_DADDR(mp, agno, > - agbno + i * igeo->blocks_per_cluster); > - if (xlog_is_buffer_cancelled(log, daddr, bb_per_cluster)) > - cancel_count++; > - } > - > - /* > - * We currently only use icreate for a single allocation at a time. This > - * means we should expect either all or none of the buffers to be > - * cancelled. Be conservative and skip replay if at least one buffer is > - * cancelled, but warn the user that something is awry if the buffers > - * are not consistent. > - * > - * XXX: This must be refined to only skip cancelled clusters once we use > - * icreate for multiple chunk allocations. > - */ > - ASSERT(!cancel_count || cancel_count == nbufs); > - if (cancel_count) { > - if (cancel_count != nbufs) > - xfs_warn(mp, > - "WARNING: partial inode chunk cancellation, skipped icreate."); > - trace_xfs_log_recover_icreate_cancel(log, icl); > - return 0; > - } > - > - trace_xfs_log_recover_icreate_recover(log, icl); > - return xfs_ialloc_inode_init(mp, NULL, buffer_list, count, agno, agbno, > - length, be32_to_cpu(icl->icl_gen)); > -} > - > STATIC int > xlog_recover_commit_pass1( > struct xlog *log, > @@ -2662,8 +2538,6 @@ xlog_recover_commit_pass2( > return xlog_recover_bui_pass2(log, item, trans->r_lsn); > case XFS_LI_BUD: > return xlog_recover_bud_pass2(log, item); > - case XFS_LI_ICREATE: > - return xlog_recover_do_icreate_pass2(log, buffer_list, item); > case XFS_LI_QUOTAOFF: > /* nothing to do in pass2 */ > return 0; > > -- chandan