mirror of
https://github.com/torvalds/linux
synced 2024-11-05 18:23:50 +00:00
xfs: refactor log recovery icreate item dispatch for pass2 commit functions
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. Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com> Reviewed-by: Chandan Babu R <chandanrlinux@gmail.com> Reviewed-by: Christoph Hellwig <hch@lst.de>
This commit is contained in:
parent
fcbdf91e0c
commit
3ec6efa703
2 changed files with 132 additions and 126 deletions
|
@ -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 */
|
||||
|
||||
|
@ -123,7 +129,133 @@ xlog_recover_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_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_ops xlog_icreate_item_ops = {
|
||||
.item_type = XFS_LI_ICREATE,
|
||||
.reorder = xlog_recover_icreate_reorder,
|
||||
.commit_pass2 = xlog_recover_icreate_commit_pass2,
|
||||
};
|
||||
|
|
|
@ -2467,130 +2467,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,
|
||||
struct xlog_recover_item *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_pass2(
|
||||
struct xlog *log,
|
||||
|
@ -2621,8 +2497,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;
|
||||
|
|
Loading…
Reference in a new issue