162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (c) 2008-2010, 2013 Dave Chinner 462306a36Sopenharmony_ci * All Rights Reserved. 562306a36Sopenharmony_ci */ 662306a36Sopenharmony_ci#include "xfs.h" 762306a36Sopenharmony_ci#include "xfs_fs.h" 862306a36Sopenharmony_ci#include "xfs_shared.h" 962306a36Sopenharmony_ci#include "xfs_format.h" 1062306a36Sopenharmony_ci#include "xfs_log_format.h" 1162306a36Sopenharmony_ci#include "xfs_trans_resv.h" 1262306a36Sopenharmony_ci#include "xfs_mount.h" 1362306a36Sopenharmony_ci#include "xfs_inode.h" 1462306a36Sopenharmony_ci#include "xfs_trans.h" 1562306a36Sopenharmony_ci#include "xfs_trans_priv.h" 1662306a36Sopenharmony_ci#include "xfs_icreate_item.h" 1762306a36Sopenharmony_ci#include "xfs_log.h" 1862306a36Sopenharmony_ci#include "xfs_log_priv.h" 1962306a36Sopenharmony_ci#include "xfs_log_recover.h" 2062306a36Sopenharmony_ci#include "xfs_ialloc.h" 2162306a36Sopenharmony_ci#include "xfs_trace.h" 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_cistruct kmem_cache *xfs_icreate_cache; /* inode create item */ 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_cistatic inline struct xfs_icreate_item *ICR_ITEM(struct xfs_log_item *lip) 2662306a36Sopenharmony_ci{ 2762306a36Sopenharmony_ci return container_of(lip, struct xfs_icreate_item, ic_item); 2862306a36Sopenharmony_ci} 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ci/* 3162306a36Sopenharmony_ci * This returns the number of iovecs needed to log the given inode item. 3262306a36Sopenharmony_ci * 3362306a36Sopenharmony_ci * We only need one iovec for the icreate log structure. 3462306a36Sopenharmony_ci */ 3562306a36Sopenharmony_ciSTATIC void 3662306a36Sopenharmony_cixfs_icreate_item_size( 3762306a36Sopenharmony_ci struct xfs_log_item *lip, 3862306a36Sopenharmony_ci int *nvecs, 3962306a36Sopenharmony_ci int *nbytes) 4062306a36Sopenharmony_ci{ 4162306a36Sopenharmony_ci *nvecs += 1; 4262306a36Sopenharmony_ci *nbytes += sizeof(struct xfs_icreate_log); 4362306a36Sopenharmony_ci} 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci/* 4662306a36Sopenharmony_ci * This is called to fill in the vector of log iovecs for the 4762306a36Sopenharmony_ci * given inode create log item. 4862306a36Sopenharmony_ci */ 4962306a36Sopenharmony_ciSTATIC void 5062306a36Sopenharmony_cixfs_icreate_item_format( 5162306a36Sopenharmony_ci struct xfs_log_item *lip, 5262306a36Sopenharmony_ci struct xfs_log_vec *lv) 5362306a36Sopenharmony_ci{ 5462306a36Sopenharmony_ci struct xfs_icreate_item *icp = ICR_ITEM(lip); 5562306a36Sopenharmony_ci struct xfs_log_iovec *vecp = NULL; 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci xlog_copy_iovec(lv, &vecp, XLOG_REG_TYPE_ICREATE, 5862306a36Sopenharmony_ci &icp->ic_format, 5962306a36Sopenharmony_ci sizeof(struct xfs_icreate_log)); 6062306a36Sopenharmony_ci} 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ciSTATIC void 6362306a36Sopenharmony_cixfs_icreate_item_release( 6462306a36Sopenharmony_ci struct xfs_log_item *lip) 6562306a36Sopenharmony_ci{ 6662306a36Sopenharmony_ci kmem_free(ICR_ITEM(lip)->ic_item.li_lv_shadow); 6762306a36Sopenharmony_ci kmem_cache_free(xfs_icreate_cache, ICR_ITEM(lip)); 6862306a36Sopenharmony_ci} 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_cistatic const struct xfs_item_ops xfs_icreate_item_ops = { 7162306a36Sopenharmony_ci .flags = XFS_ITEM_RELEASE_WHEN_COMMITTED, 7262306a36Sopenharmony_ci .iop_size = xfs_icreate_item_size, 7362306a36Sopenharmony_ci .iop_format = xfs_icreate_item_format, 7462306a36Sopenharmony_ci .iop_release = xfs_icreate_item_release, 7562306a36Sopenharmony_ci}; 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci/* 7962306a36Sopenharmony_ci * Initialize the inode log item for a newly allocated (in-core) inode. 8062306a36Sopenharmony_ci * 8162306a36Sopenharmony_ci * Inode extents can only reside within an AG. Hence specify the starting 8262306a36Sopenharmony_ci * block for the inode chunk by offset within an AG as well as the 8362306a36Sopenharmony_ci * length of the allocated extent. 8462306a36Sopenharmony_ci * 8562306a36Sopenharmony_ci * This joins the item to the transaction and marks it dirty so 8662306a36Sopenharmony_ci * that we don't need a separate call to do this, nor does the 8762306a36Sopenharmony_ci * caller need to know anything about the icreate item. 8862306a36Sopenharmony_ci */ 8962306a36Sopenharmony_civoid 9062306a36Sopenharmony_cixfs_icreate_log( 9162306a36Sopenharmony_ci struct xfs_trans *tp, 9262306a36Sopenharmony_ci xfs_agnumber_t agno, 9362306a36Sopenharmony_ci xfs_agblock_t agbno, 9462306a36Sopenharmony_ci unsigned int count, 9562306a36Sopenharmony_ci unsigned int inode_size, 9662306a36Sopenharmony_ci xfs_agblock_t length, 9762306a36Sopenharmony_ci unsigned int generation) 9862306a36Sopenharmony_ci{ 9962306a36Sopenharmony_ci struct xfs_icreate_item *icp; 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ci icp = kmem_cache_zalloc(xfs_icreate_cache, GFP_KERNEL | __GFP_NOFAIL); 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ci xfs_log_item_init(tp->t_mountp, &icp->ic_item, XFS_LI_ICREATE, 10462306a36Sopenharmony_ci &xfs_icreate_item_ops); 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_ci icp->ic_format.icl_type = XFS_LI_ICREATE; 10762306a36Sopenharmony_ci icp->ic_format.icl_size = 1; /* single vector */ 10862306a36Sopenharmony_ci icp->ic_format.icl_ag = cpu_to_be32(agno); 10962306a36Sopenharmony_ci icp->ic_format.icl_agbno = cpu_to_be32(agbno); 11062306a36Sopenharmony_ci icp->ic_format.icl_count = cpu_to_be32(count); 11162306a36Sopenharmony_ci icp->ic_format.icl_isize = cpu_to_be32(inode_size); 11262306a36Sopenharmony_ci icp->ic_format.icl_length = cpu_to_be32(length); 11362306a36Sopenharmony_ci icp->ic_format.icl_gen = cpu_to_be32(generation); 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_ci xfs_trans_add_item(tp, &icp->ic_item); 11662306a36Sopenharmony_ci tp->t_flags |= XFS_TRANS_DIRTY; 11762306a36Sopenharmony_ci set_bit(XFS_LI_DIRTY, &icp->ic_item.li_flags); 11862306a36Sopenharmony_ci} 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_cistatic enum xlog_recover_reorder 12162306a36Sopenharmony_cixlog_recover_icreate_reorder( 12262306a36Sopenharmony_ci struct xlog_recover_item *item) 12362306a36Sopenharmony_ci{ 12462306a36Sopenharmony_ci /* 12562306a36Sopenharmony_ci * Inode allocation buffers must be replayed before subsequent inode 12662306a36Sopenharmony_ci * items try to modify those buffers. ICREATE items are the logical 12762306a36Sopenharmony_ci * equivalent of logging a newly initialized inode buffer, so recover 12862306a36Sopenharmony_ci * these at the same time that we recover logged buffers. 12962306a36Sopenharmony_ci */ 13062306a36Sopenharmony_ci return XLOG_REORDER_BUFFER_LIST; 13162306a36Sopenharmony_ci} 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_ci/* 13462306a36Sopenharmony_ci * This routine is called when an inode create format structure is found in a 13562306a36Sopenharmony_ci * committed transaction in the log. It's purpose is to initialise the inodes 13662306a36Sopenharmony_ci * being allocated on disk. This requires us to get inode cluster buffers that 13762306a36Sopenharmony_ci * match the range to be initialised, stamped with inode templates and written 13862306a36Sopenharmony_ci * by delayed write so that subsequent modifications will hit the cached buffer 13962306a36Sopenharmony_ci * and only need writing out at the end of recovery. 14062306a36Sopenharmony_ci */ 14162306a36Sopenharmony_ciSTATIC int 14262306a36Sopenharmony_cixlog_recover_icreate_commit_pass2( 14362306a36Sopenharmony_ci struct xlog *log, 14462306a36Sopenharmony_ci struct list_head *buffer_list, 14562306a36Sopenharmony_ci struct xlog_recover_item *item, 14662306a36Sopenharmony_ci xfs_lsn_t lsn) 14762306a36Sopenharmony_ci{ 14862306a36Sopenharmony_ci struct xfs_mount *mp = log->l_mp; 14962306a36Sopenharmony_ci struct xfs_icreate_log *icl; 15062306a36Sopenharmony_ci struct xfs_ino_geometry *igeo = M_IGEO(mp); 15162306a36Sopenharmony_ci xfs_agnumber_t agno; 15262306a36Sopenharmony_ci xfs_agblock_t agbno; 15362306a36Sopenharmony_ci unsigned int count; 15462306a36Sopenharmony_ci unsigned int isize; 15562306a36Sopenharmony_ci xfs_agblock_t length; 15662306a36Sopenharmony_ci int bb_per_cluster; 15762306a36Sopenharmony_ci int cancel_count; 15862306a36Sopenharmony_ci int nbufs; 15962306a36Sopenharmony_ci int i; 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_ci icl = (struct xfs_icreate_log *)item->ri_buf[0].i_addr; 16262306a36Sopenharmony_ci if (icl->icl_type != XFS_LI_ICREATE) { 16362306a36Sopenharmony_ci xfs_warn(log->l_mp, "xlog_recover_do_icreate_trans: bad type"); 16462306a36Sopenharmony_ci return -EINVAL; 16562306a36Sopenharmony_ci } 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_ci if (icl->icl_size != 1) { 16862306a36Sopenharmony_ci xfs_warn(log->l_mp, "xlog_recover_do_icreate_trans: bad icl size"); 16962306a36Sopenharmony_ci return -EINVAL; 17062306a36Sopenharmony_ci } 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_ci agno = be32_to_cpu(icl->icl_ag); 17362306a36Sopenharmony_ci if (agno >= mp->m_sb.sb_agcount) { 17462306a36Sopenharmony_ci xfs_warn(log->l_mp, "xlog_recover_do_icreate_trans: bad agno"); 17562306a36Sopenharmony_ci return -EINVAL; 17662306a36Sopenharmony_ci } 17762306a36Sopenharmony_ci agbno = be32_to_cpu(icl->icl_agbno); 17862306a36Sopenharmony_ci if (!agbno || agbno == NULLAGBLOCK || agbno >= mp->m_sb.sb_agblocks) { 17962306a36Sopenharmony_ci xfs_warn(log->l_mp, "xlog_recover_do_icreate_trans: bad agbno"); 18062306a36Sopenharmony_ci return -EINVAL; 18162306a36Sopenharmony_ci } 18262306a36Sopenharmony_ci isize = be32_to_cpu(icl->icl_isize); 18362306a36Sopenharmony_ci if (isize != mp->m_sb.sb_inodesize) { 18462306a36Sopenharmony_ci xfs_warn(log->l_mp, "xlog_recover_do_icreate_trans: bad isize"); 18562306a36Sopenharmony_ci return -EINVAL; 18662306a36Sopenharmony_ci } 18762306a36Sopenharmony_ci count = be32_to_cpu(icl->icl_count); 18862306a36Sopenharmony_ci if (!count) { 18962306a36Sopenharmony_ci xfs_warn(log->l_mp, "xlog_recover_do_icreate_trans: bad count"); 19062306a36Sopenharmony_ci return -EINVAL; 19162306a36Sopenharmony_ci } 19262306a36Sopenharmony_ci length = be32_to_cpu(icl->icl_length); 19362306a36Sopenharmony_ci if (!length || length >= mp->m_sb.sb_agblocks) { 19462306a36Sopenharmony_ci xfs_warn(log->l_mp, "xlog_recover_do_icreate_trans: bad length"); 19562306a36Sopenharmony_ci return -EINVAL; 19662306a36Sopenharmony_ci } 19762306a36Sopenharmony_ci 19862306a36Sopenharmony_ci /* 19962306a36Sopenharmony_ci * The inode chunk is either full or sparse and we only support 20062306a36Sopenharmony_ci * m_ino_geo.ialloc_min_blks sized sparse allocations at this time. 20162306a36Sopenharmony_ci */ 20262306a36Sopenharmony_ci if (length != igeo->ialloc_blks && 20362306a36Sopenharmony_ci length != igeo->ialloc_min_blks) { 20462306a36Sopenharmony_ci xfs_warn(log->l_mp, 20562306a36Sopenharmony_ci "%s: unsupported chunk length", __func__); 20662306a36Sopenharmony_ci return -EINVAL; 20762306a36Sopenharmony_ci } 20862306a36Sopenharmony_ci 20962306a36Sopenharmony_ci /* verify inode count is consistent with extent length */ 21062306a36Sopenharmony_ci if ((count >> mp->m_sb.sb_inopblog) != length) { 21162306a36Sopenharmony_ci xfs_warn(log->l_mp, 21262306a36Sopenharmony_ci "%s: inconsistent inode count and chunk length", 21362306a36Sopenharmony_ci __func__); 21462306a36Sopenharmony_ci return -EINVAL; 21562306a36Sopenharmony_ci } 21662306a36Sopenharmony_ci 21762306a36Sopenharmony_ci /* 21862306a36Sopenharmony_ci * The icreate transaction can cover multiple cluster buffers and these 21962306a36Sopenharmony_ci * buffers could have been freed and reused. Check the individual 22062306a36Sopenharmony_ci * buffers for cancellation so we don't overwrite anything written after 22162306a36Sopenharmony_ci * a cancellation. 22262306a36Sopenharmony_ci */ 22362306a36Sopenharmony_ci bb_per_cluster = XFS_FSB_TO_BB(mp, igeo->blocks_per_cluster); 22462306a36Sopenharmony_ci nbufs = length / igeo->blocks_per_cluster; 22562306a36Sopenharmony_ci for (i = 0, cancel_count = 0; i < nbufs; i++) { 22662306a36Sopenharmony_ci xfs_daddr_t daddr; 22762306a36Sopenharmony_ci 22862306a36Sopenharmony_ci daddr = XFS_AGB_TO_DADDR(mp, agno, 22962306a36Sopenharmony_ci agbno + i * igeo->blocks_per_cluster); 23062306a36Sopenharmony_ci if (xlog_is_buffer_cancelled(log, daddr, bb_per_cluster)) 23162306a36Sopenharmony_ci cancel_count++; 23262306a36Sopenharmony_ci } 23362306a36Sopenharmony_ci 23462306a36Sopenharmony_ci /* 23562306a36Sopenharmony_ci * We currently only use icreate for a single allocation at a time. This 23662306a36Sopenharmony_ci * means we should expect either all or none of the buffers to be 23762306a36Sopenharmony_ci * cancelled. Be conservative and skip replay if at least one buffer is 23862306a36Sopenharmony_ci * cancelled, but warn the user that something is awry if the buffers 23962306a36Sopenharmony_ci * are not consistent. 24062306a36Sopenharmony_ci * 24162306a36Sopenharmony_ci * XXX: This must be refined to only skip cancelled clusters once we use 24262306a36Sopenharmony_ci * icreate for multiple chunk allocations. 24362306a36Sopenharmony_ci */ 24462306a36Sopenharmony_ci ASSERT(!cancel_count || cancel_count == nbufs); 24562306a36Sopenharmony_ci if (cancel_count) { 24662306a36Sopenharmony_ci if (cancel_count != nbufs) 24762306a36Sopenharmony_ci xfs_warn(mp, 24862306a36Sopenharmony_ci "WARNING: partial inode chunk cancellation, skipped icreate."); 24962306a36Sopenharmony_ci trace_xfs_log_recover_icreate_cancel(log, icl); 25062306a36Sopenharmony_ci return 0; 25162306a36Sopenharmony_ci } 25262306a36Sopenharmony_ci 25362306a36Sopenharmony_ci trace_xfs_log_recover_icreate_recover(log, icl); 25462306a36Sopenharmony_ci return xfs_ialloc_inode_init(mp, NULL, buffer_list, count, agno, agbno, 25562306a36Sopenharmony_ci length, be32_to_cpu(icl->icl_gen)); 25662306a36Sopenharmony_ci} 25762306a36Sopenharmony_ci 25862306a36Sopenharmony_ciconst struct xlog_recover_item_ops xlog_icreate_item_ops = { 25962306a36Sopenharmony_ci .item_type = XFS_LI_ICREATE, 26062306a36Sopenharmony_ci .reorder = xlog_recover_icreate_reorder, 26162306a36Sopenharmony_ci .commit_pass2 = xlog_recover_icreate_commit_pass2, 26262306a36Sopenharmony_ci}; 263