xfs: metadata directories and realtime groups
Subsystems (4)
Hi everyone,
Christoph and I have been working on getting the long-delayed metadata directory tree patchset into mergeable shape, and I think we're now satisfied that we've gotten the code to where we want it for 6.13. This time around we've included a ton of cleanups and refactorings that Dave requested during the 6.12 cycle, as well as review suggestions from the v5.0 series last week. I'm jumping on a train in a couple of hours, so I'm sending this out again.
The metadata directory tree sets us up for much more flexible metadata within an XFS filesystem. Instead of rooting inodes in the superblock which has very limited space, we instead create a directory tree that can contain arbitrary numbers of metadata files.
Having done that, we can now shard the realtime volume into multiple allocation groups, much as we do with AGs for the data device. However, the realtime volume has a fun twist -- each rtgroup gets its own space metadata files, and for that we need a metadata directory tree. Note that we also implement busy free(d) extent tracking, which means that we can do discards asynchronously.
Metadata directory trees and realtime groups also enable us to complete the realtime modernization project, which will add reverse mapping btrees, reflink, quota support, and zoned storage support for rt volumes.
Finally, quota inodes now live in the metadata directory tree, which is a pretty simple conversion. However, we added yet another new feature, which is that xfs will now remember the quota accounting and enforcement state across unmounts. You can still tweak them via mount options, but not specifying any is no longer interpreted the same as 'noquota'. Quotas for the realtime are now supported.
I'm only sending the kernel patches to the list for now (for real this time!), but please have a look at the git tree links for xfsprogs and fstests changes.
https://git.kernel.org/pub/scm/linux/kernel/git/djwong/xfs-linux.git/tag/?h=metadir_2024-10-17
https://git.kernel.org/pub/scm/linux/kernel/git/djwong/xfsprogs-dev.git/tag/?h=metadir_2024-10-17
https://git.kernel.org/pub/scm/linux/kernel/git/djwong/xfstests-dev.git/tag/?h=metadir-quotas_2024-10-17
This is a list of the kernel patches that remain unreviewed:
[PATCHSET v5.1 3/9] xfs: metadata inode directory trees
[PATCH 03/29] xfs: rename metadata inode predicates [PATCH 04/29] xfs: standardize EXPERIMENTAL warning generation
[PATCHSET v5.1 6/9] xfs: shard the realtime section
[PATCH 29/34] xfs: make xfs_rtblock_t a segmented address like
[PATCHSET v5.1 8/9] xfs: enable quota for realtime volumes
[PATCH 2/6] xfs: advertise realtime quota support in the xqm stat
--D
PATCH 1/9 xfs: convert perag to use xarrays
Hi all,
Convert the xfs_mount perag tree to use an xarray instead of a radix tree. There should be no functional changes here.
If you're going to start using this code, I strongly recommend pulling from my git trees, which are linked below.
This has been running on the djcloud for months with no problems. Enjoy! Comments and questions are, as always, welcome.
--D
kernel git tree:
https://git.kernel.org/cgit/linux/kernel/git/djwong/xfs-linux.git/log/?h=perag-xarray
xfsprogs git tree:
https://git.kernel.org/cgit/linux/kernel/git/djwong/xfsprogs-dev.git/log/?h=perag-xarray
---
Commits in this patchset:
* xfs: fix superfluous clearing of info->low in __xfs_getfsmap_datadev
* xfs: remove the unused pagb_count field in struct xfs_perag
* xfs: remove the unused pag_active_wq field in struct xfs_perag
* xfs: pass a pag to xfs_difree_inode_chunk
* xfs: remove the agno argument to xfs_free_ag_extent
* xfs: add xfs_agbno_to_fsb and xfs_agbno_to_daddr helpers
* xfs: add a xfs_agino_to_ino helper
* xfs: pass a pag to xfs_extent_busy_{search,reuse}
* xfs: keep a reference to the pag for busy extents
* xfs: remove the mount field from struct xfs_busy_extents
* xfs: remove the unused trace_xfs_iwalk_ag trace point
* xfs: remove the unused xrep_bmap_walk_rmap trace point
* xfs: constify pag arguments to trace points
* xfs: pass a perag structure to the xfs_ag_resv_init_error trace point
* xfs: pass objects to the xfs_irec_merge_{pre,post} trace points
* xfs: pass the iunlink item to the xfs_iunlink_update_dinode trace point
* xfs: pass objects to the xrep_ibt_walk_rmap tracepoint
* xfs: pass the pag to the trace_xrep_calc_ag_resblks{,_btsize} trace points
* xfs: pass the pag to the xrep_newbt_extent_class tracepoints
* xfs: convert remaining trace points to pass pag structures
* xfs: split xfs_initialize_perag
* xfs: insert the pag structures into the xarray later
--- fs/xfs/libxfs/xfs_ag.c | 125 +++++++++++++----------- fs/xfs/libxfs/xfs_ag.h | 26 +++++ fs/xfs/libxfs/xfs_ag_resv.c | 3 - fs/xfs/libxfs/xfs_alloc.c | 32 +++--- fs/xfs/libxfs/xfs_alloc.h | 5 - fs/xfs/libxfs/xfs_alloc_btree.c | 2 fs/xfs/libxfs/xfs_btree.c | 7 + fs/xfs/libxfs/xfs_ialloc.c | 67 ++++++------- fs/xfs/libxfs/xfs_ialloc_btree.c | 2 fs/xfs/libxfs/xfs_inode_util.c | 4 - fs/xfs/libxfs/xfs_refcount.c | 11 +- fs/xfs/libxfs/xfs_refcount_btree.c | 3 - fs/xfs/libxfs/xfs_rmap_btree.c | 2 fs/xfs/scrub/agheader_repair.c | 16 +-- fs/xfs/scrub/alloc_repair.c | 10 +- fs/xfs/scrub/bmap.c | 5 - fs/xfs/scrub/bmap_repair.c | 4 - fs/xfs/scrub/common.c | 2 fs/xfs/scrub/cow_repair.c | 18 +-- fs/xfs/scrub/ialloc.c | 8 +- fs/xfs/scrub/ialloc_repair.c | 25 ++--- fs/xfs/scrub/newbt.c | 46 ++++----- fs/xfs/scrub/reap.c | 8 +- fs/xfs/scrub/refcount_repair.c | 5 - fs/xfs/scrub/repair.c | 13 +- fs/xfs/scrub/rmap_repair.c | 9 +- fs/xfs/scrub/trace.h | 161 ++++++++++++++---------------- fs/xfs/xfs_discard.c | 20 ++-- fs/xfs/xfs_extent_busy.c | 31 ++---- fs/xfs/xfs_extent_busy.h | 14 +-- fs/xfs/xfs_extfree_item.c | 4 - fs/xfs/xfs_filestream.c | 5 - fs/xfs/xfs_fsmap.c | 25 ++--- fs/xfs/xfs_health.c | 8 +- fs/xfs/xfs_inode.c | 5 - fs/xfs/xfs_iunlink_item.c | 13 +- fs/xfs/xfs_iwalk.c | 17 ++- fs/xfs/xfs_log_cil.c | 3 - fs/xfs/xfs_log_recover.c | 5 - fs/xfs/xfs_trace.c | 1 fs/xfs/xfs_trace.h | 191 +++++++++++++++--------------------- fs/xfs/xfs_trans.c | 2 42 files changed, 442 insertions(+), 521 deletions(-)
PATCH 1/22 xfs: fix superfluous clearing of info->low in __xfs_getfsmap_datadev
From: Christoph Hellwig <[email protected]>
The for_each_perag helpers update the agno passed in for each iteration, and thus the "if (pag->pag_agno == start_ag)" check will always be true.
Add another variable for the loop iterator so that the field is only cleared after the first iteration.
--- fs/xfs/xfs_fsmap.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
fs/xfs/xfs_fsmap.c +3 -3
@@ -471,8 +471,7 @@ __xfs_getfsmap_datadev(struct xfs_btree_cur *bt_cur =NULL ;xfs_fsblock_t start_fsb;xfs_fsblock_t end_fsb; -xfs_agnumber_t start_ag; -xfs_agnumber_t end_ag; +xfs_agnumber_t start_ag, end_ag, ag;uint64_t eofs;int error =0 ;
@@ -520,7 +519,8 @@ __xfs_getfsmap_datadev( start_ag =XFS_FSB_TO_AGNO (mp, start_fsb); end_ag =XFS_FSB_TO_AGNO (mp, end_fsb); -for_each_perag_range (mp, start_ag, end_ag, pag) { + ag = start_ag; +for_each_perag_range (mp, ag, end_ag, pag) {/* * Set the AG high key from the fsmap high key if this * is the last AG that we're querying.
PATCH 2/22 xfs: remove the unused pagb_count field in struct xfs_perag
In reply to Darrick J. WongFrom: Christoph Hellwig <[email protected]>
--- fs/xfs/libxfs/xfs_ag.c | 1 - fs/xfs/libxfs/xfs_ag.h | 1 - 2 files changed, 2 deletions(-)
fs/xfs/libxfs/xfs_ag.c +0 -1
@@ -331,7 +331,6 @@ xfs_initialize_perag(xfs_defer_drain_init (&pag->pag_intents_drain);init_waitqueue_head (&pag->pagb_wait);init_waitqueue_head (&pag->pag_active_wq); - pag->pagb_count =0 ; pag->pagb_tree =RB_ROOT ;xfs_hooks_init (&pag->pag_rmap_update_hooks);#endif /* __KERNEL__ */
fs/xfs/libxfs/xfs_ag.h +0 -1
@@ -55,7 +55,6 @@ struct xfs_perag {xfs_agino_t pagl_leftrec;xfs_agino_t pagl_rightrec; -int pagb_count;/* pagb slots in use */ uint8_t pagf_refcount_level;/* recount btree height */ /* Blocks reserved for all kinds of metadata. */
PATCH 3/22 xfs: remove the unused pag_active_wq field in struct xfs_perag
In reply to Darrick J. WongFrom: Christoph Hellwig <[email protected]>
pag_active_wq is only woken, but never waited for.
--- fs/xfs/libxfs/xfs_ag.c | 4 +--- fs/xfs/libxfs/xfs_ag.h | 1 - 2 files changed, 1 insertion(+), 4 deletions(-)
fs/xfs/libxfs/xfs_ag.c +1 -3
@@ -107,8 +107,7 @@ xfs_perag_rele( struct xfs_perag *pag) {trace_xfs_perag_rele (pag, _RET_IP_); -if (atomic_dec_and_test (&pag->pag_active_ref)) -wake_up (&pag->pag_active_wq); +atomic_dec (&pag->pag_active_ref); }/*
@@ -330,7 +329,6 @@ xfs_initialize_perag(INIT_RADIX_TREE (&pag->pag_ici_root,GFP_ATOMIC );xfs_defer_drain_init (&pag->pag_intents_drain);init_waitqueue_head (&pag->pagb_wait); -init_waitqueue_head (&pag->pag_active_wq); pag->pagb_tree =RB_ROOT ;xfs_hooks_init (&pag->pag_rmap_update_hooks);#endif /* __KERNEL__ */
fs/xfs/libxfs/xfs_ag.h +0 -1
@@ -34,7 +34,6 @@ struct xfs_perag {xfs_agnumber_t pag_agno;/* AG this structure belongs to */ atomic_t pag_ref;/* passive reference count */ atomic_t pag_active_ref;/* active reference count */ -wait_queue_head_t pag_active_wq;/* woken active_ref falls to zero */ unsigned long pag_opstate;uint8_t pagf_bno_level;/* # of levels in bno btree */ uint8_t pagf_cnt_level;/* # of levels in cnt btree */
PATCH 4/22 xfs: pass a pag to xfs_difree_inode_chunk
In reply to Darrick J. WongFrom: Christoph Hellwig <[email protected]>
We'll want to use more than just the agno field in a bit.
--- fs/xfs/libxfs/xfs_ialloc.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
fs/xfs/libxfs/xfs_ialloc.c +3 -2
@@ -1974,10 +1974,11 @@ xfs_dialloc(static int xfs_difree_inode_chunk (struct xfs_trans *tp, -xfs_agnumber_t agno, +struct xfs_perag *pag,struct xfs_inobt_rec_incore *rec) {struct xfs_mount *mp = tp->t_mountp; +xfs_agnumber_t agno = pag->pag_agno;xfs_agblock_t sagbno =XFS_AGINO_TO_AGBNO (mp, rec->ir_startino);int startidx, endidx;
@@ -2148,7 +2149,7 @@ xfs_difree_inobt( goto error0; } - error =xfs_difree_inode_chunk (tp, pag->pag_agno, &rec); + error =xfs_difree_inode_chunk (tp, pag, &rec);if (error) goto error0; }else {
PATCH 5/22 xfs: remove the agno argument to xfs_free_ag_extent
In reply to Darrick J. WongFrom: Christoph Hellwig <[email protected]>
xfs_free_ag_extent already has a pointer to the pag structure through the agf buffer. Use that instead of passing the redundant argument, and do the same for the tracepoint.
--- fs/xfs/libxfs/xfs_alloc.c | 10 ++++------ fs/xfs/libxfs/xfs_alloc.h | 5 ++--- fs/xfs/xfs_extfree_item.c | 4 ++-- fs/xfs/xfs_trace.h | 11 +++++------ 4 files changed, 13 insertions(+), 17 deletions(-)
fs/xfs/libxfs/xfs_alloc.c +4 -6
@@ -2037,7 +2037,6 @@ intxfs_free_ag_extent ( struct xfs_trans *tp, struct xfs_buf *agbp, - xfs_agnumber_t agno, xfs_agblock_t bno, xfs_extlen_t len, const struct xfs_owner_info *oinfo,
@@ -2358,19 +2357,19 @@ xfs_free_ag_extent(* Update the freespace totals in the ag and superblock. */ error =xfs_alloc_update_counters (tp, agbp, len); -xfs_ag_resv_free_extent (agbp->b_pag, type, tp, len); +xfs_ag_resv_free_extent (pag, type, tp, len);if (error) goto error0;XFS_STATS_INC (mp, xs_freex);XFS_STATS_ADD (mp, xs_freeb, len); -trace_xfs_free_extent (mp, agno, bno, len, type, haveleft, haveright); +trace_xfs_free_extent (pag, bno, len, type, haveleft, haveright);return 0 ; error0: -trace_xfs_free_extent (mp, agno, bno, len, type,-1 ,-1 ); +trace_xfs_free_extent (pag, bno, len, type,-1 ,-1 );if (bno_cur)xfs_btree_del_cursor (bno_cur,XFS_BTREE_ERROR );if (cnt_cur)
@@ -4012,8 +4011,7 @@ __xfs_free_extent( goto err_release; } - error =xfs_free_ag_extent (tp, agbp, pag->pag_agno, agbno, len, oinfo, - type); + error =xfs_free_ag_extent (tp, agbp, agbno, len, oinfo, type);if (error) goto err_release;
fs/xfs/libxfs/xfs_alloc.h +2 -3
@@ -79,9 +79,8 @@ int xfs_alloc_put_freelist(struct xfs_perag *pag, struct xfs_trans *tp, struct xfs_buf *agfbp, struct xfs_buf *agflbp, xfs_agblock_t bno, int btreeblk);int xfs_free_ag_extent (struct xfs_trans *tp,struct xfs_buf *agbp, -xfs_agnumber_t agno,xfs_agblock_t bno, -xfs_extlen_t len,const struct xfs_owner_info *oinfo, -enum xfs_ag_resv_type type); +xfs_agblock_t bno,xfs_extlen_t len, +const struct xfs_owner_info *oinfo,enum xfs_ag_resv_type type);/* * Compute and fill in value of m_alloc_maxlevels.
fs/xfs/xfs_extfree_item.c +2 -2
@@ -547,8 +547,8 @@ xfs_agfl_free_finish_item( error =xfs_alloc_read_agf (xefi->xefi_pag, tp,0 , &agbp);if (!error) - error =xfs_free_ag_extent (tp, agbp, xefi->xefi_pag->pag_agno, - agbno,1 , &oinfo,XFS_AG_RESV_AGFL ); + error =xfs_free_ag_extent (tp, agbp, agbno,1 , &oinfo, +XFS_AG_RESV_AGFL );xfs_efd_add_extent (efdp, xefi);xfs_extent_free_cancel_item (&xefi->xefi_list);
fs/xfs/xfs_trace.h +5 -6
@@ -1763,10 +1763,9 @@ DEFINE_AGF_EVENT(xfs_agf);DEFINE_AGF_EVENT (xfs_agfl_reset); TRACE_EVENT(xfs_free_extent, - TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno, xfs_agblock_t agbno, - xfs_extlen_t len, enum xfs_ag_resv_type resv, int haveleft, - int haveright), - TP_ARGS(mp, agno, agbno, len, resv, haveleft, haveright), + TP_PROTO(struct xfs_perag *pag, xfs_agblock_t agbno, xfs_extlen_t len, + enum xfs_ag_resv_type resv, int haveleft, int haveright), + TP_ARGS(pag, agbno, len, resv, haveleft, haveright), TP_STRUCT__entry( __field(dev_t, dev) __field(xfs_agnumber_t, agno)
@@ -1777,8 +1776,8 @@ TRACE_EVENT(xfs_free_extent,__field (int, haveright) ),TP_fast_assign ( - __entry->dev = mp->m_super->s_dev; - __entry->agno = agno; + __entry->dev = pag->pag_mount->m_super->s_dev; + __entry->agno = pag->pag_agno; __entry->agbno = agbno; __entry->len = len; __entry->resv = resv;
PATCH 6/22 xfs: add xfs_agbno_to_fsb and xfs_agbno_to_daddr helpers
In reply to Darrick J. WongFrom: Christoph Hellwig <[email protected]>
Add helpers to convert an agbno to a daddr or fsbno based on a pag structure.
This provides a simpler conversion and better type safety compared to the existing code that passes the mount structure and the agno separately.
--- fs/xfs/libxfs/xfs_ag.c | 2 +- fs/xfs/libxfs/xfs_ag.h | 16 ++++++++++++++++ fs/xfs/libxfs/xfs_alloc.c | 14 ++++++-------- fs/xfs/libxfs/xfs_btree.c | 7 +++---- fs/xfs/libxfs/xfs_ialloc.c | 29 +++++++++++++---------------- fs/xfs/libxfs/xfs_ialloc_btree.c | 2 +- fs/xfs/libxfs/xfs_refcount.c | 11 ++++------- fs/xfs/libxfs/xfs_refcount_btree.c | 3 +-- fs/xfs/scrub/bmap.c | 5 ++--- fs/xfs/scrub/bmap_repair.c | 4 +--- fs/xfs/scrub/cow_repair.c | 18 +++++++----------- fs/xfs/scrub/ialloc.c | 2 +- fs/xfs/scrub/ialloc_repair.c | 13 +++++-------- fs/xfs/scrub/newbt.c | 17 +++++++---------- fs/xfs/scrub/reap.c | 8 +++----- fs/xfs/scrub/refcount_repair.c | 5 ++--- fs/xfs/scrub/repair.c | 2 +- fs/xfs/scrub/rmap_repair.c | 5 ++--- fs/xfs/xfs_filestream.c | 5 ++--- fs/xfs/xfs_fsmap.c | 19 ++++++------------- fs/xfs/xfs_iwalk.c | 3 +-- 21 files changed, 85 insertions(+), 105 deletions(-)
fs/xfs/libxfs/xfs_ag.c +1 -1
@@ -873,7 +873,7 @@ xfs_ag_shrink_space(/* internal log shouldn't also show up in the free space btrees */ error =xfs_alloc_vextent_exact_bno (&args, -XFS_AGB_TO_FSB (mp, pag->pag_agno, aglen - delta)); +xfs_agbno_to_fsb (pag, aglen - delta));if (!error && args.agbno ==NULLAGBLOCK ) error = -ENOSPC ;
fs/xfs/libxfs/xfs_ag.h +16 -0
@@ -330,4 +330,20 @@ int xfs_ag_extend_space(struct xfs_perag *pag, struct xfs_trans *tp, xfs_extlen_t len);int xfs_ag_get_geometry (struct xfs_perag *pag,struct xfs_ag_geometry *ageo); +static inline xfs_fsblock_t +xfs_agbno_to_fsb ( +struct xfs_perag *pag, +xfs_agblock_t agbno) +{ +return XFS_AGB_TO_FSB (pag->pag_mount, pag->pag_agno, agbno); +} + +static inline xfs_daddr_t +xfs_agbno_to_daddr ( +struct xfs_perag *pag, +xfs_agblock_t agbno) +{ +return XFS_AGB_TO_DADDR (pag->pag_mount, pag->pag_agno, agbno); +} +#endif /* __LIBXFS_AG_H */
fs/xfs/libxfs/xfs_alloc.c +6 -8
@@ -1259,7 +1259,7 @@ xfs_alloc_ag_vextent_small(struct xfs_buf *bp; error =xfs_trans_get_buf (args->tp, args->mp->m_ddev_targp, -XFS_AGB_TO_DADDR (args->mp, args->agno, fbno), +xfs_agbno_to_daddr (args->pag, fbno), args->mp->m_bsize,0 , &bp);if (error) goto error;
@@ -2933,9 +2933,8 @@ xfs_alloc_fix_freelist(* Deferring the free disconnects freeing up the AGFL slot from * freeing the block. */ - error =xfs_free_extent_later (tp, -XFS_AGB_TO_FSB (mp, args->agno, bno),1 , - &targs.oinfo,XFS_AG_RESV_AGFL ,0 ); + error =xfs_free_extent_later (tp,xfs_agbno_to_fsb (pag, bno), +1 , &targs.oinfo,XFS_AG_RESV_AGFL ,0 );if (error) goto out_agbp_relse; }
@@ -3596,7 +3595,7 @@ xfs_alloc_vextent_finish( goto out_drop_perag; } - args->fsbno =XFS_AGB_TO_FSB (mp, args->agno, args->agbno); + args->fsbno =xfs_agbno_to_fsb (args->pag, args->agbno);ASSERT (args->len >= args->minlen);ASSERT (args->len <= args->maxlen);
@@ -3648,7 +3647,6 @@ xfs_alloc_vextent_this_ag( struct xfs_alloc_arg *args, xfs_agnumber_t agno) { -struct xfs_mount *mp = args->mp;xfs_agnumber_t minimum_agno;uint32_t alloc_flags =0 ;int error;
@@ -3661,8 +3659,8 @@ xfs_alloc_vextent_this_ag(trace_xfs_alloc_vextent_this_ag (args); - error =xfs_alloc_vextent_check_args (args,XFS_AGB_TO_FSB (mp, agno,0 ), - &minimum_agno); + error =xfs_alloc_vextent_check_args (args, +xfs_agbno_to_fsb (args->pag,0 ), &minimum_agno);if (error) {if (error == -ENOSPC )return 0 ;
fs/xfs/libxfs/xfs_btree.c +3 -4
@@ -1017,21 +1017,20 @@ xfs_btree_readahead_agblock( struct xfs_btree_block *block) {struct xfs_mount *mp = cur->bc_mp; -xfs_agnumber_t agno = cur->bc_ag.pag->pag_agno;xfs_agblock_t left =be32_to_cpu (block->bb_u.s.bb_leftsib);xfs_agblock_t right =be32_to_cpu (block->bb_u.s.bb_rightsib);int rval =0 ;if ((lr &XFS_BTCUR_LEFTRA ) && left !=NULLAGBLOCK ) {xfs_buf_readahead (mp->m_ddev_targp, -XFS_AGB_TO_DADDR (mp, agno, left), +xfs_agbno_to_daddr (cur->bc_ag.pag, left), mp->m_bsize, cur->bc_ops->buf_ops); rval++; }if ((lr &XFS_BTCUR_RIGHTRA ) && right !=NULLAGBLOCK ) {xfs_buf_readahead (mp->m_ddev_targp, -XFS_AGB_TO_DADDR (mp, agno, right), +xfs_agbno_to_daddr (cur->bc_ag.pag, right), mp->m_bsize, cur->bc_ops->buf_ops); rval++; }
@@ -1091,7 +1090,7 @@ xfs_btree_ptr_to_daddr(switch (cur->bc_ops->type) {case XFS_BTREE_TYPE_AG : - *daddr =XFS_AGB_TO_DADDR (cur->bc_mp, cur->bc_ag.pag->pag_agno, + *daddr =xfs_agbno_to_daddr (cur->bc_ag.pag,be32_to_cpu (ptr->s));break ;case XFS_BTREE_TYPE_INODE :
fs/xfs/libxfs/xfs_ialloc.c +13 -16
@@ -768,8 +768,7 @@ xfs_ialloc_ag_alloc(/* Allow space for the inode btree to split. */ args.minleft = igeo->inobt_maxlevels; error =xfs_alloc_vextent_exact_bno (&args, -XFS_AGB_TO_FSB (args.mp, pag->pag_agno, - args.agbno)); +xfs_agbno_to_fsb (pag, args.agbno));if (error)return error;
@@ -811,8 +810,8 @@ xfs_ialloc_ag_alloc(*/ args.minleft = igeo->inobt_maxlevels; error =xfs_alloc_vextent_near_bno (&args, -XFS_AGB_TO_FSB (args.mp, pag->pag_agno, -be32_to_cpu (agi->agi_root))); +xfs_agbno_to_fsb (pag, +be32_to_cpu (agi->agi_root)));if (error)return error; }
@@ -824,8 +823,8 @@ xfs_ialloc_ag_alloc(if (isaligned && args.fsbno ==NULLFSBLOCK ) { args.alignment = igeo->cluster_align; error =xfs_alloc_vextent_near_bno (&args, -XFS_AGB_TO_FSB (args.mp, pag->pag_agno, -be32_to_cpu (agi->agi_root))); +xfs_agbno_to_fsb (pag, +be32_to_cpu (agi->agi_root)));if (error)return error; }
@@ -860,8 +859,8 @@ xfs_ialloc_ag_alloc( igeo->ialloc_blks; error =xfs_alloc_vextent_near_bno (&args, -XFS_AGB_TO_FSB (args.mp, pag->pag_agno, -be32_to_cpu (agi->agi_root))); +xfs_agbno_to_fsb (pag, +be32_to_cpu (agi->agi_root)));if (error)return error;
@@ -1978,7 +1977,6 @@ xfs_difree_inode_chunk( struct xfs_inobt_rec_incore *rec) {struct xfs_mount *mp = tp->t_mountp; -xfs_agnumber_t agno = pag->pag_agno;xfs_agblock_t sagbno =XFS_AGINO_TO_AGBNO (mp, rec->ir_startino);int startidx, endidx;
@@ -1989,8 +1987,7 @@ xfs_difree_inode_chunk(if (!xfs_inobt_issparse (rec->ir_holemask)) {/* not sparse, calculate extent info directly */ -return xfs_free_extent_later (tp, -XFS_AGB_TO_FSB (mp, agno, sagbno), +return xfs_free_extent_later (tp,xfs_agbno_to_fsb (pag, sagbno),M_IGEO (mp)->ialloc_blks, &XFS_RMAP_OINFO_INODES ,XFS_AG_RESV_NONE ,0 ); }
@@ -2036,9 +2033,9 @@ xfs_difree_inode_chunk(ASSERT (agbno % mp->m_sb.sb_spino_align ==0 );ASSERT (contigblk % mp->m_sb.sb_spino_align ==0 ); - error =xfs_free_extent_later (tp, -XFS_AGB_TO_FSB (mp, agno, agbno), contigblk, - &XFS_RMAP_OINFO_INODES ,XFS_AG_RESV_NONE ,0 ); + error =xfs_free_extent_later (tp,xfs_agbno_to_fsb (pag, agbno), + contigblk, &XFS_RMAP_OINFO_INODES , +XFS_AG_RESV_NONE ,0 );if (error)return error;
@@ -2508,7 +2505,7 @@ xfs_imap( offset =XFS_INO_TO_OFFSET (mp, ino);ASSERT (offset < mp->m_sb.sb_inopblock); - imap->im_blkno =XFS_AGB_TO_DADDR (mp, pag->pag_agno, agbno); + imap->im_blkno =xfs_agbno_to_daddr (pag, agbno); imap->im_len =XFS_FSB_TO_BB (mp,1 ); imap->im_boffset = (unsigned short )(offset << mp->m_sb.sb_inodelog);
@@ -2538,7 +2535,7 @@ xfs_imap( offset = ((agbno - cluster_agbno) * mp->m_sb.sb_inopblock) +XFS_INO_TO_OFFSET (mp, ino); - imap->im_blkno =XFS_AGB_TO_DADDR (mp, pag->pag_agno, cluster_agbno); + imap->im_blkno =xfs_agbno_to_daddr (pag, cluster_agbno); imap->im_len =XFS_FSB_TO_BB (mp,M_IGEO (mp)->blocks_per_cluster); imap->im_boffset = (unsigned short )(offset << mp->m_sb.sb_inodelog);
fs/xfs/libxfs/xfs_ialloc_btree.c +1 -1
@@ -120,7 +120,7 @@ __xfs_inobt_alloc_block( args.resv = resv; error =xfs_alloc_vextent_near_bno (&args, -XFS_AGB_TO_FSB (args.mp, args.pag->pag_agno, sbno)); +xfs_agbno_to_fsb (args.pag, sbno));if (error)return error;
fs/xfs/libxfs/xfs_refcount.c +4 -7
@@ -1154,8 +1154,7 @@ xfs_refcount_adjust_extents( goto out_error; } }else { - fsbno =XFS_AGB_TO_FSB (cur->bc_mp, - cur->bc_ag.pag->pag_agno, + fsbno =xfs_agbno_to_fsb (cur->bc_ag.pag, tmp.rc_startblock); error = xfs_free_extent_later(cur->bc_tp, fsbno, tmp.rc_blockcount, NULL,
@@ -1217,8 +1216,7 @@ xfs_refcount_adjust_extents( } goto advloop; }else { - fsbno =XFS_AGB_TO_FSB (cur->bc_mp, - cur->bc_ag.pag->pag_agno, + fsbno =xfs_agbno_to_fsb (cur->bc_ag.pag, ext.rc_startblock); error = xfs_free_extent_later(cur->bc_tp, fsbno, ext.rc_blockcount, NULL,
@@ -1320,7 +1318,7 @@ xfs_refcount_continue_op(return -EFSCORRUPTED ; } - ri->ri_startblock =XFS_AGB_TO_FSB (mp, pag->pag_agno, new_agbno); + ri->ri_startblock =xfs_agbno_to_fsb (pag, new_agbno);ASSERT (xfs_verify_fsbext (mp, ri->ri_startblock, ri->ri_blockcount));ASSERT (pag->pag_agno ==XFS_FSB_TO_AGNO (mp, ri->ri_startblock));
@@ -1956,8 +1954,7 @@ xfs_refcount_recover_cow_leftovers( goto out_free;/* Free the orphan record */ - fsb =XFS_AGB_TO_FSB (mp, pag->pag_agno, - rr->rr_rrec.rc_startblock); + fsb =xfs_agbno_to_fsb (pag, rr->rr_rrec.rc_startblock);xfs_refcount_free_cow_extent (tp, fsb, rr->rr_rrec.rc_blockcount);
fs/xfs/libxfs/xfs_refcount_btree.c +1 -2
@@ -74,8 +74,7 @@ xfs_refcountbt_alloc_block( args.resv =XFS_AG_RESV_METADATA ; error =xfs_alloc_vextent_near_bno (&args, -XFS_AGB_TO_FSB (args.mp, args.pag->pag_agno, -xfs_refc_block (args.mp))); +xfs_agbno_to_fsb (args.pag,xfs_refc_block (args.mp)));if (error) goto out_error;if (args.fsbno ==NULLFSBLOCK ) {
fs/xfs/scrub/bmap.c +2 -3
@@ -600,9 +600,8 @@ xchk_bmap_check_rmap(if (irec.br_startoff != check_rec.rm_offset)xchk_fblock_set_corrupt (sc, sbcri->whichfork, check_rec.rm_offset); -if (irec.br_startblock !=XFS_AGB_TO_FSB (sc->mp, - cur->bc_ag.pag->pag_agno, - check_rec.rm_startblock)) +if (irec.br_startblock != +xfs_agbno_to_fsb (cur->bc_ag.pag, check_rec.rm_startblock))xchk_fblock_set_corrupt (sc, sbcri->whichfork, check_rec.rm_offset);if (irec.br_blockcount > check_rec.rm_blockcount)
fs/xfs/scrub/bmap_repair.c +1 -3
@@ -237,7 +237,6 @@ xrep_bmap_walk_rmap( void *priv) {struct xrep_bmap *rb = priv; -struct xfs_mount *mp = cur->bc_mp;xfs_fsblock_t fsbno;int error =0 ;
@@ -269,8 +268,7 @@ xrep_bmap_walk_rmap(if ((rec->rm_flags &XFS_RMAP_UNWRITTEN ) && !rb->allow_unwritten)return -EFSCORRUPTED ; - fsbno =XFS_AGB_TO_FSB (mp, cur->bc_ag.pag->pag_agno, - rec->rm_startblock); + fsbno =xfs_agbno_to_fsb (cur->bc_ag.pag, rec->rm_startblock);if (rec->rm_flags &XFS_RMAP_BMBT_BLOCK ) { rb->old_bmbt_block_count += rec->rm_blockcount;
fs/xfs/scrub/cow_repair.c +7 -11
@@ -137,7 +137,6 @@ xrep_cow_mark_shared_staging( {struct xrep_cow *xc = priv;struct xfs_refcount_irec rrec; -xfs_fsblock_t fsbno;if (!xfs_refcount_check_domain (rec) || rec->rc_domain !=XFS_REFC_DOMAIN_SHARED )
@@ -145,9 +144,9 @@ xrep_cow_mark_shared_staging(xrep_cow_trim_refcount (xc, &rrec, rec); - fsbno =XFS_AGB_TO_FSB (xc->sc->mp, cur->bc_ag.pag->pag_agno, - rrec.rc_startblock); -return xrep_cow_mark_file_range (xc, fsbno, rrec.rc_blockcount); +return xrep_cow_mark_file_range (xc, +xfs_agbno_to_fsb (cur->bc_ag.pag, rrec.rc_startblock), + rrec.rc_blockcount); }/*
@@ -178,8 +177,7 @@ xrep_cow_mark_missing_staging( goto next; error =xrep_cow_mark_file_range (xc, -XFS_AGB_TO_FSB (xc->sc->mp, cur->bc_ag.pag->pag_agno, - xc->next_bno), +xfs_agbno_to_fsb (cur->bc_ag.pag, xc->next_bno), rrec.rc_startblock - xc->next_bno);if (error)return error;
@@ -200,7 +198,6 @@ xrep_cow_mark_missing_staging_rmap( void *priv) {struct xrep_cow *xc = priv; -xfs_fsblock_t fsbno;xfs_agblock_t rec_bno;xfs_extlen_t rec_len;unsigned int adj;
@@ -222,8 +219,8 @@ xrep_cow_mark_missing_staging_rmap( rec_len -= adj; } - fsbno =XFS_AGB_TO_FSB (xc->sc->mp, cur->bc_ag.pag->pag_agno, rec_bno); -return xrep_cow_mark_file_range (xc, fsbno, rec_len); +return xrep_cow_mark_file_range (xc, +xfs_agbno_to_fsb (cur->bc_ag.pag, rec_bno), rec_len); }/*
@@ -275,8 +272,7 @@ xrep_cow_find_bad(if (xc->next_bno < xc->irec_startbno + xc->irec.br_blockcount) { error =xrep_cow_mark_file_range (xc, -XFS_AGB_TO_FSB (sc->mp, pag->pag_agno, - xc->next_bno), +xfs_agbno_to_fsb (pag, xc->next_bno), xc->irec_startbno + xc->irec.br_blockcount - xc->next_bno);if (error)
fs/xfs/scrub/ialloc.c +1 -1
@@ -396,7 +396,7 @@ xchk_iallocbt_check_cluster(* ir_startino can be large enough to make im_boffset nonzero. */ ir_holemask = (irec->ir_holemask & cluster_mask); - imap.im_blkno =XFS_AGB_TO_DADDR (mp, agno, agbno); + imap.im_blkno =xfs_agbno_to_daddr (bs->cur->bc_ag.pag, agbno); imap.im_len =XFS_FSB_TO_BB (mp,M_IGEO (mp)->blocks_per_cluster); imap.im_boffset =XFS_INO_TO_OFFSET (mp, irec->ir_startino) << mp->m_sb.sb_inodelog;
fs/xfs/scrub/ialloc_repair.c +5 -8
@@ -307,7 +307,7 @@ xrep_ibt_process_cluster(* inobt because imap_to_bp directly maps the buffer without touching * either inode btree. */ - imap.im_blkno =XFS_AGB_TO_DADDR (mp, sc->sa.pag->pag_agno, cluster_bno); + imap.im_blkno =xfs_agbno_to_daddr (sc->sa.pag, cluster_bno); imap.im_len =XFS_FSB_TO_BB (mp, igeo->blocks_per_cluster); imap.im_boffset =0 ; error =xfs_imap_to_bp (mp, sc->tp, &imap, &cluster_bp);
@@ -634,7 +634,6 @@ xrep_ibt_build_new_trees(struct xfs_scrub *sc = ri->sc;struct xfs_btree_cur *ino_cur;struct xfs_btree_cur *fino_cur =NULL ; -xfs_fsblock_t fsbno;bool need_finobt;int error;
@@ -656,9 +655,8 @@ xrep_ibt_build_new_trees(* * Start by setting up the inobt staging cursor. */ - fsbno =XFS_AGB_TO_FSB (sc->mp, sc->sa.pag->pag_agno, -XFS_IBT_BLOCK (sc->mp)); -xrep_newbt_init_ag (&ri->new_inobt, sc, &XFS_RMAP_OINFO_INOBT , fsbno, +xrep_newbt_init_ag (&ri->new_inobt, sc, &XFS_RMAP_OINFO_INOBT , +xfs_agbno_to_fsb (sc->sa.pag,XFS_IBT_BLOCK (sc->mp)),XFS_AG_RESV_NONE ); ri->new_inobt.bload.claim_block = xrep_ibt_claim_block; ri->new_inobt.bload.get_records = xrep_ibt_get_records;
@@ -677,10 +675,9 @@ xrep_ibt_build_new_trees(if (sc->mp->m_finobt_nores) resv =XFS_AG_RESV_NONE ; - fsbno =XFS_AGB_TO_FSB (sc->mp, sc->sa.pag->pag_agno, -XFS_FIBT_BLOCK (sc->mp));xrep_newbt_init_ag (&ri->new_finobt, sc, &XFS_RMAP_OINFO_INOBT , - fsbno, resv); +xfs_agbno_to_fsb (sc->sa.pag,XFS_FIBT_BLOCK (sc->mp)), + resv); ri->new_finobt.bload.claim_block = xrep_fibt_claim_block; ri->new_finobt.bload.get_records = xrep_fibt_get_records;
fs/xfs/scrub/newbt.c +7 -10
@@ -186,11 +186,10 @@ xrep_newbt_add_extent( xfs_agblock_t agbno, xfs_extlen_t len) { -struct xfs_mount *mp = xnr->sc->mp;struct xfs_alloc_arg args = { .tp =NULL ,/* no autoreap */ .oinfo = xnr->oinfo, - .fsbno =XFS_AGB_TO_FSB (mp, pag->pag_agno, agbno), + .fsbno =xfs_agbno_to_fsb (pag, agbno), .len = len, .resv = xnr->resv, };
@@ -210,8 +209,8 @@ xrep_newbt_validate_ag_alloc_hint( xfs_verify_fsbno(sc->mp, xnr->alloc_hint)) return; - xnr->alloc_hint =XFS_AGB_TO_FSB (sc->mp, sc->sa.pag->pag_agno, -XFS_AGFL_BLOCK (sc->mp) +1 ); + xnr->alloc_hint = +xfs_agbno_to_fsb (sc->sa.pag,XFS_AGFL_BLOCK (sc->mp) +1 ); }/* Allocate disk space for a new per-AG btree. */
@@ -376,7 +375,6 @@ xrep_newbt_free_extent(struct xfs_scrub *sc = xnr->sc;xfs_agblock_t free_agbno = resv->agbno;xfs_extlen_t free_aglen = resv->len; -xfs_fsblock_t fsbno;int error;if (!btree_committed || resv->used ==0 ) {
@@ -413,9 +411,9 @@ xrep_newbt_free_extent(* Use EFIs to free the reservations. This reduces the chance * that we leak blocks if the system goes down. */ - fsbno =XFS_AGB_TO_FSB (sc->mp, resv->pag->pag_agno, free_agbno); - error =xfs_free_extent_later (sc->tp, fsbno, free_aglen, &xnr->oinfo, - xnr->resv,XFS_FREE_EXTENT_SKIP_DISCARD ); + error =xfs_free_extent_later (sc->tp, +xfs_agbno_to_fsb (resv->pag, free_agbno), free_aglen, + &xnr->oinfo, xnr->resv,XFS_FREE_EXTENT_SKIP_DISCARD );if (error)return error;
@@ -545,8 +543,7 @@ xrep_newbt_claim_block( xnr->oinfo.oi_owner);if (cur->bc_ops->ptr_len ==XFS_BTREE_LONG_PTR_LEN ) - ptr->l =cpu_to_be64 (XFS_AGB_TO_FSB (mp, resv->pag->pag_agno, - agbno)); + ptr->l =cpu_to_be64 (xfs_agbno_to_fsb (resv->pag, agbno));else ptr->s =cpu_to_be32 (agbno);
fs/xfs/scrub/reap.c +3 -5
@@ -263,7 +263,6 @@ xreap_agextent_binval(struct xfs_scrub *sc = rs->sc;struct xfs_perag *pag = sc->sa.pag;struct xfs_mount *mp = sc->mp; -xfs_agnumber_t agno = sc->sa.pag->pag_agno;xfs_agblock_t agbno_next = agbno + *aglenp;xfs_agblock_t bno = agbno;
@@ -284,7 +283,7 @@ xreap_agextent_binval(*/ while (bno < agbno_next) {struct xrep_bufscan scan = { - .daddr =XFS_AGB_TO_DADDR (mp, agno, bno), + .daddr =xfs_agbno_to_daddr (pag, bno), .max_sectors =xrep_bufscan_max_sectors (mp, agbno_next - bno), .daddr_step =XFS_FSB_TO_BB (mp,1 ),
@@ -391,7 +390,7 @@ xreap_agextent_iter(xfs_fsblock_t fsbno;int error =0 ; - fsbno =XFS_AGB_TO_FSB (sc->mp, sc->sa.pag->pag_agno, agbno); + fsbno =xfs_agbno_to_fsb (sc->sa.pag, agbno);/* * If there are other rmappings, this block is cross linked and must
@@ -780,7 +779,6 @@ xreap_bmapi_binval(xfs_fileoff_t off;xfs_fileoff_t max_off;xfs_extlen_t scan_blocks; -xfs_agnumber_t agno = sc->sa.pag->pag_agno;xfs_agblock_t bno;xfs_agblock_t agbno;xfs_agblock_t agbno_next;
@@ -837,7 +835,7 @@ xreap_bmapi_binval(*/ while (bno < agbno_next) {struct xrep_bufscan scan = { - .daddr =XFS_AGB_TO_DADDR (mp, agno, bno), + .daddr =xfs_agbno_to_daddr (pag, bno), .max_sectors =xrep_bufscan_max_sectors (mp, scan_blocks), .daddr_step =XFS_FSB_TO_BB (mp,1 ),
fs/xfs/scrub/refcount_repair.c +2 -3
@@ -590,7 +590,6 @@ xrep_refc_build_new_tree(struct xfs_scrub *sc = rr->sc;struct xfs_btree_cur *refc_cur;struct xfs_perag *pag = sc->sa.pag; -xfs_fsblock_t fsbno;int error; error =xrep_refc_sort_records (rr);
@@ -603,8 +602,8 @@ xrep_refc_build_new_tree(* to root the new btree while it's under construction and before we * attach it to the AG header. */ - fsbno =XFS_AGB_TO_FSB (sc->mp, pag->pag_agno,xfs_refc_block (sc->mp)); -xrep_newbt_init_ag (&rr->new_btree, sc, &XFS_RMAP_OINFO_REFC , fsbno, +xrep_newbt_init_ag (&rr->new_btree, sc, &XFS_RMAP_OINFO_REFC , +xfs_agbno_to_fsb (pag,xfs_refc_block (sc->mp)),XFS_AG_RESV_METADATA ); rr->new_btree.bload.get_records = xrep_refc_get_records; rr->new_btree.bload.claim_block = xrep_refc_claim_block;
fs/xfs/scrub/repair.c +1 -1
@@ -483,7 +483,7 @@ xrep_findroot_block(int block_level;int error =0 ; - daddr =XFS_AGB_TO_DADDR (mp, ri->sc->sa.pag->pag_agno, agbno); + daddr =xfs_agbno_to_daddr (ri->sc->sa.pag, agbno);/* * Blocks in the AGFL have stale contents that might just happen to
fs/xfs/scrub/rmap_repair.c +2 -3
@@ -1272,7 +1272,6 @@ xrep_rmap_build_new_tree(struct xfs_perag *pag = sc->sa.pag;struct xfs_agf *agf = sc->sa.agf_bp->b_addr;struct xfs_btree_cur *rmap_cur; -xfs_fsblock_t fsbno;int error;/*
@@ -1290,9 +1289,9 @@ xrep_rmap_build_new_tree(* rmapbt per-AG reservation, which we will adjust further after * committing the new btree. */ - fsbno =XFS_AGB_TO_FSB (sc->mp, pag->pag_agno,XFS_RMAP_BLOCK (sc->mp));xrep_newbt_init_ag (&rr->new_btree, sc, &XFS_RMAP_OINFO_SKIP_UPDATE , - fsbno,XFS_AG_RESV_RMAPBT ); +xfs_agbno_to_fsb (pag,XFS_RMAP_BLOCK (sc->mp)), +XFS_AG_RESV_RMAPBT ); rr->new_btree.bload.get_records = xrep_rmap_get_records; rr->new_btree.bload.claim_block = xrep_rmap_claim_block; rr->new_btree.alloc_vextent = xrep_rmap_alloc_vextent;
fs/xfs/xfs_filestream.c +2 -3
@@ -230,7 +230,7 @@ xfs_filestream_lookup_association(trace_xfs_filestream_lookup (pag, ap->ip->i_ino); - ap->blkno =XFS_AGB_TO_FSB (args->mp, pag->pag_agno,0 ); + ap->blkno =xfs_agbno_to_fsb (pag,0 );xfs_bmap_adjacent (ap);/*
@@ -347,7 +347,6 @@ xfs_filestream_select_ag(struct xfs_alloc_arg *args, xfs_extlen_t *longest) { - struct xfs_mount *mp = args->mp; struct xfs_inode *pip;xfs_ino_t ino =0 ;int error =0 ;
@@ -373,7 +372,7 @@ xfs_filestream_select_ag(return error; out_select: - ap->blkno =XFS_AGB_TO_FSB (mp, args->pag->pag_agno,0 ); + ap->blkno =xfs_agbno_to_fsb (args->pag,0 );return 0 ; }
fs/xfs/xfs_fsmap.c +6 -13
@@ -391,15 +391,11 @@ xfs_getfsmap_datadev_helper(const struct xfs_rmap_irec *rec, void *priv) { - struct xfs_mount *mp = cur->bc_mp; struct xfs_getfsmap_info *info = priv; -xfs_fsblock_t fsb; -xfs_daddr_t rec_daddr; - fsb =XFS_AGB_TO_FSB (mp, cur->bc_ag.pag->pag_agno, rec->rm_startblock); - rec_daddr =XFS_FSB_TO_DADDR (mp, fsb); - -return xfs_getfsmap_helper (cur->bc_tp, info, rec, rec_daddr,0 ); +return xfs_getfsmap_helper (cur->bc_tp, info, rec, +xfs_agbno_to_daddr (cur->bc_ag.pag, rec->rm_startblock), +0 ); }/* Transform a bnobt irec into a fsmap */
@@ -409,13 +405,8 @@ xfs_getfsmap_datadev_bnobt_helper(const struct xfs_alloc_rec_incore *rec, void *priv) { - struct xfs_mount *mp = cur->bc_mp; struct xfs_getfsmap_info *info = priv;struct xfs_rmap_irec irec; -xfs_daddr_t rec_daddr; - - rec_daddr =XFS_AGB_TO_DADDR (mp, cur->bc_ag.pag->pag_agno, - rec->ar_startblock); irec.rm_startblock = rec->ar_startblock; irec.rm_blockcount = rec->ar_blockcount;
@@ -423,7 +414,9 @@ xfs_getfsmap_datadev_bnobt_helper( irec.rm_offset =0 ; irec.rm_flags =0 ; -return xfs_getfsmap_helper (cur->bc_tp, info, &irec, rec_daddr,0 ); +return xfs_getfsmap_helper (cur->bc_tp, info, &irec, +xfs_agbno_to_daddr (cur->bc_ag.pag, rec->ar_startblock), +0 ); }/* Set rmap flags based on the getfsmap flags */
fs/xfs/xfs_iwalk.c +1 -2
@@ -100,7 +100,6 @@ xfs_iwalk_ichunk_ra( struct xfs_inobt_rec_incore *irec) {struct xfs_ino_geometry *igeo =M_IGEO (mp); -xfs_agnumber_t agno = pag->pag_agno;xfs_agblock_t agbno;struct blk_plug plug;int i;/* inode chunk index */
@@ -114,7 +113,7 @@ xfs_iwalk_ichunk_ra( imask =xfs_inobt_maskn (i, igeo->inodes_per_cluster);if (imask & ~irec->ir_free) {xfs_buf_readahead (mp->m_ddev_targp, -XFS_AGB_TO_DADDR (mp, agno, agbno), +xfs_agbno_to_daddr (pag, agbno), igeo->blocks_per_cluster * mp->m_bsize, &xfs_inode_buf_ops); }
PATCH 7/22 xfs: add a xfs_agino_to_ino helper
In reply to Darrick J. WongFrom: Christoph Hellwig <[email protected]>
Add a helpers to convert an agino to an ino based on a pag structure.
This provides a simpler conversion and better type safety compared to the existing code that passes the mount structure and the agno separately.
--- fs/xfs/libxfs/xfs_ag.h | 8 ++++++++ fs/xfs/libxfs/xfs_ialloc.c | 24 +++++++++++------------- fs/xfs/scrub/agheader_repair.c | 16 ++++------------ fs/xfs/scrub/common.c | 2 +- fs/xfs/scrub/ialloc.c | 3 +-- fs/xfs/scrub/ialloc_repair.c | 6 ++---- fs/xfs/xfs_inode.c | 5 ++--- fs/xfs/xfs_iwalk.c | 12 ++++++------ fs/xfs/xfs_log_recover.c | 5 ++--- 9 files changed, 37 insertions(+), 44 deletions(-)
fs/xfs/libxfs/xfs_ag.h +8 -0
@@ -346,4 +346,12 @@ xfs_agbno_to_daddr( return XFS_AGB_TO_DADDR(pag->pag_mount, pag->pag_agno, agbno); } +static inline xfs_ino_t +xfs_agino_to_ino ( +struct xfs_perag *pag, +xfs_agino_t agino) +{ +return XFS_AGINO_TO_INO (pag->pag_mount, pag->pag_agno, agino); +} +#endif /* __LIBXFS_AG_H */
fs/xfs/libxfs/xfs_ialloc.c +11 -13
@@ -914,8 +914,7 @@ xfs_ialloc_ag_alloc(if (error == -EFSCORRUPTED ) {xfs_alert (args.mp,"invalid sparse inode record: ino 0x%llx holemask 0x%x count %u" , -XFS_AGINO_TO_INO (args.mp, pag->pag_agno, - rec.ir_startino), +xfs_agino_to_ino (pag, rec.ir_startino), rec.ir_holemask, rec.ir_count);xfs_force_shutdown (args.mp,SHUTDOWN_CORRUPT_INCORE ); }
@@ -1334,7 +1333,7 @@ xfs_dialloc_ag_inobt(ASSERT (offset <XFS_INODES_PER_CHUNK );ASSERT ((XFS_AGINO_TO_OFFSET (mp, rec.ir_startino) %XFS_INODES_PER_CHUNK ) ==0 ); - ino =XFS_AGINO_TO_INO (mp, pag->pag_agno, rec.ir_startino + offset); + ino =xfs_agino_to_ino (pag, rec.ir_startino + offset);if (xfs_ag_has_sickness (pag,XFS_SICK_AG_INODES )) { error =xfs_dialloc_check_ino (pag, tp, ino);
@@ -1615,7 +1614,7 @@ xfs_dialloc_ag(ASSERT (offset <XFS_INODES_PER_CHUNK );ASSERT ((XFS_AGINO_TO_OFFSET (mp, rec.ir_startino) %XFS_INODES_PER_CHUNK ) ==0 ); - ino =XFS_AGINO_TO_INO (mp, pag->pag_agno, rec.ir_startino + offset); + ino =xfs_agino_to_ino (pag, rec.ir_startino + offset);if (xfs_ag_has_sickness (pag,XFS_SICK_AG_INODES )) { error =xfs_dialloc_check_ino (pag, tp, ino);
@@ -2122,8 +2121,7 @@ xfs_difree_inobt(if (!xfs_has_ikeep (mp) && rec.ir_free ==XFS_INOBT_ALL_FREE && mp->m_sb.sb_inopblock <=XFS_INODES_PER_CHUNK ) { xic->deleted = true; - xic->first_ino =XFS_AGINO_TO_INO (mp, pag->pag_agno, - rec.ir_startino); + xic->first_ino =xfs_agino_to_ino (pag, rec.ir_startino); xic->alloc =xfs_inobt_irec_to_allocmask (&rec);/*
@@ -2322,10 +2320,10 @@ xfs_difree(return -EINVAL ; } agino =XFS_INO_TO_AGINO (mp, inode); -if (inode !=XFS_AGINO_TO_INO (mp, pag->pag_agno, agino)) { -xfs_warn (mp,"%s: inode != XFS_AGINO_TO_INO() (%llu != %llu)." , +if (inode !=xfs_agino_to_ino (pag, agino)) { +xfs_warn (mp,"%s: inode != xfs_agino_to_ino() (%llu != %llu)." , __func__, (unsigned long long )inode, - (unsigned long long )XFS_AGINO_TO_INO (mp, pag->pag_agno, agino)); + (unsigned long long )xfs_agino_to_ino (pag, agino));ASSERT (0 );return -EINVAL ; }
@@ -2456,7 +2454,7 @@ xfs_imap( agino =XFS_INO_TO_AGINO (mp, ino); agbno =XFS_AGINO_TO_AGBNO (mp, agino);if (agbno >= mp->m_sb.sb_agblocks || - ino !=XFS_AGINO_TO_INO (mp, pag->pag_agno, agino)) { + ino !=xfs_agino_to_ino (pag, agino)) { error = -EINVAL ;#ifdef DEBUG /*
@@ -2471,11 +2469,11 @@ xfs_imap( __func__, (unsigned long long )agbno, (unsigned long)mp->m_sb.sb_agblocks); } -if (ino !=XFS_AGINO_TO_INO (mp, pag->pag_agno, agino)) { +if (ino !=xfs_agino_to_ino (pag, agino)) {xfs_alert (mp, -"%s: ino (0x%llx) != XFS_AGINO_TO_INO() (0x%llx)" , +"%s: ino (0x%llx) != xfs_agino_to_ino() (0x%llx)" , __func__, ino, -XFS_AGINO_TO_INO (mp, pag->pag_agno, agino)); +xfs_agino_to_ino (pag, agino)); }xfs_stack_trace ();#endif /* DEBUG */
fs/xfs/scrub/agheader_repair.c +4 -12
@@ -1038,12 +1038,10 @@ xrep_iunlink_reload_next( {struct xfs_scrub *sc = ragi->sc;struct xfs_inode *ip; -xfs_ino_t ino;xfs_agino_t ret =NULLAGINO ;int error; - ino =XFS_AGINO_TO_INO (sc->mp, sc->sa.pag->pag_agno, agino); - error =xchk_iget (ragi->sc, ino, &ip); + error =xchk_iget (ragi->sc,xfs_agino_to_ino (sc->sa.pag, agino), &ip);if (error)return ret;
@@ -1278,9 +1276,7 @@ xrep_iunlink_mark_ondisk_rec(* on because we haven't actually scrubbed the inobt or the * inodes yet. */ - error =xchk_iget (ragi->sc, -XFS_AGINO_TO_INO (mp, sc->sa.pag->pag_agno, - agino), + error =xchk_iget (ragi->sc,xfs_agino_to_ino (sc->sa.pag, agino), &ip);if (error)continue ;
@@ -1539,15 +1535,13 @@ xrep_iunlink_relink_next( ip =xfs_iunlink_lookup (pag, agino);if (!ip) { -xfs_ino_t ino;xfs_agino_t prev_agino;/* * No inode exists in cache. Load it off the disk so that we * can reinsert it into the incore unlinked list. */ - ino =XFS_AGINO_TO_INO (sc->mp, pag->pag_agno, agino); - error =xchk_iget (sc, ino, &ip); + error =xchk_iget (sc,xfs_agino_to_ino (pag, agino), &ip);if (error)return -EFSCORRUPTED ;
@@ -1601,15 +1595,13 @@ xrep_iunlink_relink_prev( ip =xfs_iunlink_lookup (pag, agino);if (!ip) { -xfs_ino_t ino;xfs_agino_t next_agino;/* * No inode exists in cache. Load it off the disk so that we * can reinsert it into the incore unlinked list. */ - ino =XFS_AGINO_TO_INO (sc->mp, pag->pag_agno, agino); - error =xchk_iget (sc, ino, &ip); + error =xchk_iget (sc,xfs_agino_to_ino (pag, agino), &ip);if (error)return -EFSCORRUPTED ;
fs/xfs/scrub/common.c +1 -1
@@ -1336,7 +1336,7 @@ xchk_inode_is_allocated( }/* reject inode numbers outside existing AGs */ - ino =XFS_AGINO_TO_INO (sc->mp, pag->pag_agno, agino); + ino =xfs_agino_to_ino (pag, agino);if (!xfs_verify_ino (mp, ino))return -EINVAL ;
fs/xfs/scrub/ialloc.c +1 -2
@@ -303,7 +303,6 @@ xchk_iallocbt_check_cluster_ifree(unsigned int irec_ino, struct xfs_dinode *dip) { - struct xfs_mount *mp = bs->cur->bc_mp; xfs_ino_t fsino;xfs_agino_t agino;bool irec_free;
@@ -319,7 +318,7 @@ xchk_iallocbt_check_cluster_ifree(* the record, compute which fs inode we're talking about. */ agino = irec->ir_startino + irec_ino; - fsino =XFS_AGINO_TO_INO (mp, bs->cur->bc_ag.pag->pag_agno, agino); + fsino =xfs_agino_to_ino (bs->cur->bc_ag.pag, agino); irec_free = (irec->ir_free &XFS_INOBT_MASK (irec_ino)); if (be16_to_cpu(dip->di_magic) != XFS_DINODE_MAGIC ||
fs/xfs/scrub/ialloc_repair.c +2 -4
@@ -146,15 +146,12 @@ xrep_ibt_check_ifree(struct xfs_scrub *sc = ri->sc;struct xfs_mount *mp = sc->mp;struct xfs_dinode *dip; -xfs_ino_t fsino;xfs_agino_t agino; -xfs_agnumber_t agno = ri->sc->sa.pag->pag_agno;unsigned int cluster_buf_base;unsigned int offset;int error; agino = cluster_ag_base + cluster_index; - fsino =XFS_AGINO_TO_INO (mp, agno, agino);/* Inode uncached or half assembled, read disk buffer */ cluster_buf_base =XFS_INO_TO_OFFSET (mp, cluster_ag_base);
@@ -165,7 +162,8 @@ xrep_ibt_check_ifree(if (be16_to_cpu (dip->di_magic) !=XFS_DINODE_MAGIC )return -EFSCORRUPTED ; -if (dip->di_version >=3 &&be64_to_cpu (dip->di_ino) != fsino) +if (dip->di_version >=3 && +be64_to_cpu (dip->di_ino) !=xfs_agino_to_ino (ri->sc->sa.pag, agino))return -EFSCORRUPTED ;/* Will the in-core inode tell us if it's in use? */
fs/xfs/xfs_inode.c +2 -3
@@ -1516,7 +1516,6 @@ xfs_iunlink_reload_next(struct xfs_perag *pag = agibp->b_pag;struct xfs_mount *mp = pag->pag_mount;struct xfs_inode *next_ip =NULL ; -xfs_ino_t ino;int error;ASSERT (next_agino !=NULLAGINO );
@@ -1538,8 +1537,8 @@ xfs_iunlink_reload_next(* but we'd rather shut down now since we're already running in a weird * situation. */ - ino =XFS_AGINO_TO_INO (mp, pag->pag_agno, next_agino); - error =xfs_iget (mp, tp, ino,XFS_IGET_UNTRUSTED ,0 , &next_ip); + error =xfs_iget (mp, tp,xfs_agino_to_ino (pag, next_agino), +XFS_IGET_UNTRUSTED ,0 , &next_ip);if (error) {xfs_ag_mark_sick (pag,XFS_SICK_AG_AGI );return error;
fs/xfs/xfs_iwalk.c +6 -6
@@ -176,7 +176,6 @@ xfs_iwalk_ag_recs(struct xfs_mount *mp = iwag->mp;struct xfs_trans *tp = iwag->tp;struct xfs_perag *pag = iwag->pag; -xfs_ino_t ino;unsigned int i, j;int error;
@@ -207,9 +206,10 @@ xfs_iwalk_ag_recs(continue ;/* Otherwise call our function. */ - ino =XFS_AGINO_TO_INO (mp, pag->pag_agno, - irec->ir_startino + j); - error = iwag->iwalk_fn (mp, tp, ino, iwag->data); + error = iwag->iwalk_fn (mp, tp, +xfs_agino_to_ino (pag, + irec->ir_startino + j), + iwag->data);if (error)return error; }
@@ -304,7 +304,7 @@ xfs_iwalk_ag_start(return -EFSCORRUPTED ; } - iwag->lastino =XFS_AGINO_TO_INO (mp, pag->pag_agno, + iwag->lastino =xfs_agino_to_ino (pag, irec->ir_startino +XFS_INODES_PER_CHUNK -1 );/*
@@ -424,7 +424,7 @@ xfs_iwalk_ag(break ;/* Make sure that we always move forward. */ - rec_fsino =XFS_AGINO_TO_INO (mp, pag->pag_agno, irec->ir_startino); + rec_fsino =xfs_agino_to_ino (pag, irec->ir_startino);if (iwag->lastino !=NULLFSINO &&XFS_IS_CORRUPT (mp, iwag->lastino >= rec_fsino)) {xfs_btree_mark_sick (cur);
fs/xfs/xfs_log_recover.c +2 -3
@@ -2726,9 +2726,8 @@ xlog_recover_iunlink_bucket( agino =be32_to_cpu (agi->agi_unlinked[bucket]);while (agino !=NULLAGINO ) { - error =xfs_iget (mp,NULL , -XFS_AGINO_TO_INO (mp, pag->pag_agno, agino), -0 ,0 , &ip); + error =xfs_iget (mp,NULL ,xfs_agino_to_ino (pag, agino),0 ,0 , + &ip);if (error)break ;
PATCH 8/22 xfs: pass a pag to xfs_extent_busy_{search,reuse}
In reply to Darrick J. WongFrom: Christoph Hellwig <[email protected]>
Replace the [mp,agno] tuple with the perag structure, which will become more useful later.
--- fs/xfs/libxfs/xfs_alloc.c | 4 ++-- fs/xfs/libxfs/xfs_alloc_btree.c | 2 +- fs/xfs/libxfs/xfs_rmap_btree.c | 2 +- fs/xfs/xfs_discard.c | 2 +- fs/xfs/xfs_extent_busy.c | 12 ++++-------- fs/xfs/xfs_extent_busy.h | 8 ++++---- 6 files changed, 13 insertions(+), 17 deletions(-)
fs/xfs/libxfs/xfs_alloc.c +2 -2
@@ -1252,7 +1252,7 @@ xfs_alloc_ag_vextent_small(if (fbno ==NULLAGBLOCK ) goto out; -xfs_extent_busy_reuse (args->mp, args->pag, fbno,1 , +xfs_extent_busy_reuse (args->pag, fbno,1 , (args->datatype &XFS_ALLOC_NOBUSY ));if (args->datatype &XFS_ALLOC_USERDATA ) {
@@ -3616,7 +3616,7 @@ xfs_alloc_vextent_finish(if (error) goto out_drop_perag; -ASSERT (!xfs_extent_busy_search (mp, args->pag, args->agbno, +ASSERT (!xfs_extent_busy_search (args->pag, args->agbno, args->len)); }
fs/xfs/libxfs/xfs_alloc_btree.c +1 -1
@@ -86,7 +86,7 @@ xfs_allocbt_alloc_block( }atomic64_inc (&cur->bc_mp->m_allocbt_blks); -xfs_extent_busy_reuse (cur->bc_mp, cur->bc_ag.pag, bno,1 , false); +xfs_extent_busy_reuse (cur->bc_ag.pag, bno,1 , false); new->s =cpu_to_be32 (bno);
fs/xfs/libxfs/xfs_rmap_btree.c +1 -1
@@ -102,7 +102,7 @@ xfs_rmapbt_alloc_block(return 0 ; } -xfs_extent_busy_reuse (cur->bc_mp, pag, bno,1 , false); +xfs_extent_busy_reuse (pag, bno,1 , false); new->s =cpu_to_be32 (bno);be32_add_cpu (&agf->agf_rmap_blocks,1 );
fs/xfs/xfs_discard.c +1 -1
@@ -272,7 +272,7 @@ xfs_trim_gather_extents(* If any blocks in the range are still busy, skip the * discard and try again the next time. */ -if (xfs_extent_busy_search (mp, pag, fbno, flen)) { +if (xfs_extent_busy_search (pag, fbno, flen)) {trace_xfs_discard_busy (mp, pag->pag_agno, fbno, flen); goto next_extent; }
fs/xfs/xfs_extent_busy.c +4 -8
@@ -101,7 +101,6 @@ xfs_extent_busy_insert_discard(*/ int xfs_extent_busy_search ( -struct xfs_mount *mp,struct xfs_perag *pag,xfs_agblock_t bno,xfs_extlen_t len)
@@ -148,7 +147,6 @@ xfs_extent_busy_search(*/ STATIC bool xfs_extent_busy_update_extent( - struct xfs_mount *mp, struct xfs_perag *pag, struct xfs_extent_busy *busyp, xfs_agblock_t fbno,
@@ -280,24 +278,22 @@ xfs_extent_busy_update_extent(ASSERT (0 ); } -trace_xfs_extent_busy_reuse (mp, pag->pag_agno, fbno, flen); +trace_xfs_extent_busy_reuse (pag->pag_mount, pag->pag_agno, fbno, flen);return true; out_force_log:spin_unlock (&pag->pagb_lock); -xfs_log_force (mp,XFS_LOG_SYNC ); -trace_xfs_extent_busy_force (mp, pag->pag_agno, fbno, flen); +xfs_log_force (pag->pag_mount,XFS_LOG_SYNC ); +trace_xfs_extent_busy_force (pag->pag_mount, pag->pag_agno, fbno, flen);spin_lock (&pag->pagb_lock);return false; } -/* * For a given extent [fbno, flen], make sure we can reuse it safely. */ void xfs_extent_busy_reuse( - struct xfs_mount *mp, struct xfs_perag *pag, xfs_agblock_t fbno, xfs_extlen_t flen,
@@ -323,7 +319,7 @@ xfs_extent_busy_reuse(continue ; } -if (!xfs_extent_busy_update_extent (mp, pag, busyp, fbno, flen, +if (!xfs_extent_busy_update_extent (pag, busyp, fbno, flen, userdata)) goto restart; }
fs/xfs/xfs_extent_busy.h +4 -4
@@ -58,12 +58,12 @@ xfs_extent_busy_clear(struct xfs_mount *mp, struct list_head *list, bool do_discard);int -xfs_extent_busy_search (struct xfs_mount *mp,struct xfs_perag *pag, -xfs_agblock_t bno,xfs_extlen_t len); +xfs_extent_busy_search (struct xfs_perag *pag,xfs_agblock_t bno, +xfs_extlen_t len);void -xfs_extent_busy_reuse (struct xfs_mount *mp,struct xfs_perag *pag, -xfs_agblock_t fbno,xfs_extlen_t flen,bool userdata); +xfs_extent_busy_reuse (struct xfs_perag *pag,xfs_agblock_t fbno, +xfs_extlen_t flen,bool userdata); bool xfs_extent_busy_trim(struct xfs_alloc_arg *args, xfs_agblock_t *bno,
PATCH 9/22 xfs: keep a reference to the pag for busy extents
In reply to Darrick J. WongFrom: Christoph Hellwig <[email protected]>
Processing of busy extents requires the perag structure, so keep the reference while they are in flight.
--- fs/xfs/xfs_discard.c | 4 ++-- fs/xfs/xfs_extent_busy.c | 15 ++++++++------- fs/xfs/xfs_extent_busy.h | 2 +- 3 files changed, 11 insertions(+), 10 deletions(-)
fs/xfs/xfs_discard.c +2 -2
@@ -117,11 +117,11 @@ xfs_discard_extents(blk_start_plug (&plug);list_for_each_entry (busyp, &extents->extent_list, list) { -trace_xfs_discard_extent (mp, busyp->agno, busyp->bno, +trace_xfs_discard_extent (mp, busyp->pag->pag_agno, busyp->bno, busyp->length); error =__blkdev_issue_discard (mp->m_ddev_targp->bt_bdev, -XFS_AGB_TO_DADDR (mp, busyp->agno, busyp->bno), +xfs_agbno_to_daddr (busyp->pag, busyp->bno),XFS_FSB_TO_BB (mp, busyp->length),GFP_KERNEL , &bio);if (error && error != -EOPNOTSUPP ) {
fs/xfs/xfs_extent_busy.c +8 -7
@@ -34,7 +34,7 @@ xfs_extent_busy_insert_list( new =kzalloc (sizeof (struct xfs_extent_busy ),GFP_KERNEL | __GFP_NOFAIL); - new->agno = pag->pag_agno; + new->pag =xfs_perag_hold (pag); new->bno = bno; new->length = len;INIT_LIST_HEAD (&new->list);
@@ -526,12 +526,14 @@ xfs_extent_busy_clear_one( busyp->flags =XFS_EXTENT_BUSY_DISCARDED ;return false; } -trace_xfs_extent_busy_clear (pag->pag_mount, busyp->agno, - busyp->bno, busyp->length); +trace_xfs_extent_busy_clear (pag->pag_mount, + busyp->pag->pag_agno, busyp->bno, + busyp->length);rb_erase (&busyp->rb_node, &pag->pagb_tree); }list_del_init (&busyp->list); +xfs_perag_put (busyp->pag);kfree (busyp);return true; }
@@ -554,10 +556,9 @@ xfs_extent_busy_clear(return ; do { + struct xfs_perag *pag = xfs_perag_hold(busyp->pag); bool wakeup = false; - struct xfs_perag *pag; - pag = xfs_perag_get(mp, busyp->agno); spin_lock(&pag->pagb_lock); do { next = list_next_entry(busyp, list);
@@ -565,7 +566,7 @@ xfs_extent_busy_clear( wakeup = true; busyp = next; }while (!list_entry_is_head (busyp, list, list) && - busyp->agno == pag->pag_agno); + busyp->pag == pag);if (wakeup) { pag->pagb_gen++;
@@ -662,7 +663,7 @@ xfs_extent_busy_ag_cmp( container_of(l2, struct xfs_extent_busy, list);s32 diff; - diff = b1->agno - b2->agno; + diff = b1->pag->pag_agno - b2->pag->pag_agno;if (!diff) diff = b1->bno - b2->bno;return diff;
fs/xfs/xfs_extent_busy.h +1 -1
@@ -20,7 +20,7 @@ struct xfs_alloc_arg;struct xfs_extent_busy {struct rb_node rb_node;/* ag by-bno indexed search tree */ struct list_head list;/* transaction busy extent list */ -xfs_agnumber_t agno; +struct xfs_perag *pag;xfs_agblock_t bno;xfs_extlen_t length;unsigned int flags;
PATCH 10/22 xfs: remove the mount field from struct xfs_busy_extents
In reply to Darrick J. WongFrom: Christoph Hellwig <[email protected]>
The mount field is only passed to xfs_extent_busy_clear, which never uses it.
--- fs/xfs/xfs_discard.c | 5 ++--- fs/xfs/xfs_extent_busy.c | 1 - fs/xfs/xfs_extent_busy.h | 4 +--- fs/xfs/xfs_log_cil.c | 3 +-- fs/xfs/xfs_trans.c | 2 +- 5 files changed, 5 insertions(+), 10 deletions(-)
fs/xfs/xfs_discard.c +2 -3
@@ -81,7 +81,7 @@ xfs_discard_endio_work(struct xfs_busy_extents *extents = container_of(work, struct xfs_busy_extents, endio_work); -xfs_extent_busy_clear (extents->mount, &extents->extent_list, false); +xfs_extent_busy_clear (&extents->extent_list, false);kfree (extents->owner); }
@@ -301,7 +301,7 @@ xfs_trim_gather_extents(* we aren't going to issue a discard on them any more. */ if (error) -xfs_extent_busy_clear (mp, &extents->extent_list, false); +xfs_extent_busy_clear (&extents->extent_list, false); out_del_cursor:xfs_btree_del_cursor (cur, error); out_trans_cancel:
@@ -347,7 +347,6 @@ xfs_trim_perag_extents(break ; } - extents->mount = pag->pag_mount; extents->owner = extents;INIT_LIST_HEAD (&extents->extent_list);
fs/xfs/xfs_extent_busy.c +0 -1
@@ -545,7 +545,6 @@ xfs_extent_busy_clear_one(*/ void xfs_extent_busy_clear ( -struct xfs_mount *mp,struct list_head *list,bool do_discard) {
fs/xfs/xfs_extent_busy.h +1 -3
@@ -33,7 +33,6 @@ struct xfs_extent_busy {* to discard completion. */ struct xfs_busy_extents { -struct xfs_mount *mount;struct list_head extent_list;struct work_struct endio_work;
@@ -54,8 +53,7 @@ xfs_extent_busy_insert_discard(struct xfs_perag *pag, xfs_agblock_t bno, xfs_extlen_t len, struct list_head *busy_list);void -xfs_extent_busy_clear (struct xfs_mount *mp,struct list_head *list, -bool do_discard); +xfs_extent_busy_clear (struct list_head *list,bool do_discard); int xfs_extent_busy_search(struct xfs_perag *pag, xfs_agblock_t bno,
fs/xfs/xfs_log_cil.c +1 -2
@@ -907,7 +907,7 @@ xlog_cil_committed(xlog_cil_ail_insert (ctx, abort);xfs_extent_busy_sort (&ctx->busy_extents.extent_list); -xfs_extent_busy_clear (mp, &ctx->busy_extents.extent_list, +xfs_extent_busy_clear (&ctx->busy_extents.extent_list,xfs_has_discard (mp) && !abort);spin_lock (&ctx->cil->xc_push_lock);
@@ -917,7 +917,6 @@ xlog_cil_committed(xlog_cil_free_logvec (&ctx->lv_chain);if (!list_empty (&ctx->busy_extents.extent_list)) { - ctx->busy_extents.mount = mp; ctx->busy_extents.owner = ctx;xfs_discard_extents (mp, &ctx->busy_extents);return ;
fs/xfs/xfs_trans.c +1 -1
@@ -67,7 +67,7 @@ xfs_trans_free( struct xfs_trans *tp) {xfs_extent_busy_sort (&tp->t_busy); -xfs_extent_busy_clear (tp->t_mountp, &tp->t_busy, false); +xfs_extent_busy_clear (&tp->t_busy, false);trace_xfs_trans_free (tp, _RET_IP_);xfs_trans_clear_context (tp);
PATCH 11/22 xfs: remove the unused trace_xfs_iwalk_ag trace point
In reply to Darrick J. WongFrom: Christoph Hellwig <[email protected]>
--- fs/xfs/xfs_trace.h | 19 ------------------- 1 file changed, 19 deletions(-)
fs/xfs/xfs_trace.h +0 -19
@@ -4242,25 +4242,6 @@ DEFINE_INODE_CORRUPT_EVENT(xfs_inode_mark_corrupt);DEFINE_INODE_CORRUPT_EVENT (xfs_inode_mark_healthy);DEFINE_INODE_CORRUPT_EVENT (xfs_inode_unfixed_corruption); -TRACE_EVENT (xfs_iwalk_ag, - TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno, - xfs_agino_t startino), -TP_ARGS (mp, agno, startino), -TP_STRUCT__entry ( - __field(dev_t, dev) - __field(xfs_agnumber_t, agno) -__field (xfs_agino_t, startino) - ), -TP_fast_assign ( - __entry->dev = mp->m_super->s_dev; - __entry->agno = agno; - __entry->startino = startino; - ), -TP_printk ("dev %d:%d agno 0x%x startino 0x%x" , -MAJOR (__entry->dev),MINOR (__entry->dev), __entry->agno, - __entry->startino) -) - TRACE_EVENT(xfs_iwalk_ag_rec, TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno, struct xfs_inobt_rec_incore *irec),
PATCH 12/22 xfs: remove the unused xrep_bmap_walk_rmap trace point
In reply to Darrick J. WongFrom: Christoph Hellwig <[email protected]>
--- fs/xfs/scrub/trace.h | 1 - 1 file changed, 1 deletion(-)
fs/xfs/scrub/trace.h +0 -1
@@ -2020,7 +2020,6 @@ DEFINE_EVENT(xrep_rmap_class, name, \ uint64_t owner, uint64_t offset, unsigned int flags), \ TP_ARGS(mp, agno, agbno, len, owner, offset, flags)) DEFINE_REPAIR_RMAP_EVENT(xrep_ibt_walk_rmap); -DEFINE_REPAIR_RMAP_EVENT (xrep_bmap_walk_rmap); TRACE_EVENT(xrep_abt_found, TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno,
PATCH 13/22 xfs: constify pag arguments to trace points
In reply to Darrick J. WongFrom: Christoph Hellwig <[email protected]>
Trace points never modify their arguments. Mark all the pag objects passed to trace points. The exception is the xfs_ag_resv_class, which uses the xfs_perag_resv helper that can't be marked const due to other users modifying the returned structure.
--- fs/xfs/scrub/trace.h | 34 +++++++++++++++++++--------------- fs/xfs/xfs_trace.h | 19 ++++++++++--------- 2 files changed, 29 insertions(+), 24 deletions(-)
fs/xfs/scrub/trace.h +19 -15
@@ -922,7 +922,8 @@ DEFINE_XCHK_FSFREEZE_EVENT(xchk_fsfreeze);DEFINE_XCHK_FSFREEZE_EVENT (xchk_fsthaw); TRACE_EVENT(xchk_refcount_incorrect, - TP_PROTO(struct xfs_perag *pag, const struct xfs_refcount_irec *irec, + TP_PROTO(const struct xfs_perag *pag, + const struct xfs_refcount_irec *irec, xfs_nlink_t seen), TP_ARGS(pag, irec, seen), TP_STRUCT__entry(
@@ -1918,7 +1919,8 @@ TRACE_EVENT(xchk_dirtree_live_update,#if IS_ENABLED (CONFIG_XFS_ONLINE_REPAIR ) DECLARE_EVENT_CLASS(xrep_extent_class, - TP_PROTO(struct xfs_perag *pag, xfs_agblock_t agbno, xfs_extlen_t len), + TP_PROTO(const struct xfs_perag *pag, xfs_agblock_t agbno, + xfs_extlen_t len), TP_ARGS(pag, agbno, len), TP_STRUCT__entry( __field(dev_t, dev)
@@ -1940,7 +1942,8 @@ DECLARE_EVENT_CLASS(xrep_extent_class, );#define DEFINE_REPAIR_EXTENT_EVENT (name) \ DEFINE_EVENT(xrep_extent_class, name, \ - TP_PROTO(struct xfs_perag *pag, xfs_agblock_t agbno, xfs_extlen_t len), \ + TP_PROTO(const struct xfs_perag *pag, xfs_agblock_t agbno, \ + xfs_extlen_t len), \ TP_ARGS(pag, agbno, len))DEFINE_REPAIR_EXTENT_EVENT (xreap_dispose_unmap_extent);DEFINE_REPAIR_EXTENT_EVENT (xreap_dispose_free_extent);
@@ -1949,8 +1952,8 @@ DEFINE_REPAIR_EXTENT_EVENT(xreap_bmapi_binval);DEFINE_REPAIR_EXTENT_EVENT (xrep_agfl_insert); DECLARE_EVENT_CLASS(xrep_reap_find_class, - TP_PROTO(struct xfs_perag *pag, xfs_agblock_t agbno, xfs_extlen_t len, - bool crosslinked), + TP_PROTO(const struct xfs_perag *pag, xfs_agblock_t agbno, + xfs_extlen_t len, bool crosslinked), TP_ARGS(pag, agbno, len, crosslinked), TP_STRUCT__entry( __field(dev_t, dev)
@@ -1975,8 +1978,8 @@ DECLARE_EVENT_CLASS(xrep_reap_find_class, );#define DEFINE_REPAIR_REAP_FIND_EVENT (name) \ DEFINE_EVENT(xrep_reap_find_class, name, \ - TP_PROTO(struct xfs_perag *pag, xfs_agblock_t agbno, xfs_extlen_t len, \ - bool crosslinked), \ + TP_PROTO(const struct xfs_perag *pag, xfs_agblock_t agbno, \ + xfs_extlen_t len, bool crosslinked), \ TP_ARGS(pag, agbno, len, crosslinked))DEFINE_REPAIR_REAP_FIND_EVENT (xreap_agextent_select);DEFINE_REPAIR_REAP_FIND_EVENT (xreap_bmapi_select);
@@ -2077,7 +2080,8 @@ TRACE_EVENT(xrep_ibt_found, ) TRACE_EVENT(xrep_refc_found, - TP_PROTO(struct xfs_perag *pag, const struct xfs_refcount_irec *rec), + TP_PROTO(const struct xfs_perag *pag, + const struct xfs_refcount_irec *rec), TP_ARGS(pag, rec), TP_STRUCT__entry( __field(dev_t, dev)
@@ -2595,7 +2599,7 @@ TRACE_EVENT(xrep_cow_replace_mapping, ); TRACE_EVENT(xrep_cow_free_staging, - TP_PROTO(struct xfs_perag *pag, xfs_agblock_t agbno, + TP_PROTO(const struct xfs_perag *pag, xfs_agblock_t agbno, xfs_extlen_t blockcount), TP_ARGS(pag, agbno, blockcount), TP_STRUCT__entry(
@@ -3312,7 +3316,7 @@ DEFINE_XREP_SYMLINK_EVENT(xrep_symlink_rebuild);DEFINE_XREP_SYMLINK_EVENT (xrep_symlink_reset_fork); TRACE_EVENT(xrep_iunlink_visit, - TP_PROTO(struct xfs_perag *pag, unsigned int bucket, + TP_PROTO(const struct xfs_perag *pag, unsigned int bucket, xfs_agino_t bucket_agino, struct xfs_inode *ip), TP_ARGS(pag, bucket, bucket_agino, ip), TP_STRUCT__entry(
@@ -3402,7 +3406,7 @@ TRACE_EVENT(xrep_iunlink_reload_ondisk, ); TRACE_EVENT(xrep_iunlink_walk_ondisk_bucket, - TP_PROTO(struct xfs_perag *pag, unsigned int bucket, + TP_PROTO(const struct xfs_perag *pag, unsigned int bucket, xfs_agino_t prev_agino, xfs_agino_t next_agino), TP_ARGS(pag, bucket, prev_agino, next_agino), TP_STRUCT__entry(
@@ -3428,7 +3432,7 @@ TRACE_EVENT(xrep_iunlink_walk_ondisk_bucket, ); DECLARE_EVENT_CLASS(xrep_iunlink_resolve_class, - TP_PROTO(struct xfs_perag *pag, unsigned int bucket, + TP_PROTO(const struct xfs_perag *pag, unsigned int bucket, xfs_agino_t prev_agino, xfs_agino_t next_agino), TP_ARGS(pag, bucket, prev_agino, next_agino), TP_STRUCT__entry(
@@ -3454,7 +3458,7 @@ DECLARE_EVENT_CLASS(xrep_iunlink_resolve_class, );#define DEFINE_REPAIR_IUNLINK_RESOLVE_EVENT (name) \ DEFINE_EVENT(xrep_iunlink_resolve_class, name, \ - TP_PROTO(struct xfs_perag *pag, unsigned int bucket, \ + TP_PROTO(const struct xfs_perag *pag, unsigned int bucket, \ xfs_agino_t prev_agino, xfs_agino_t next_agino), \ TP_ARGS(pag, bucket, prev_agino, next_agino))DEFINE_REPAIR_IUNLINK_RESOLVE_EVENT (xrep_iunlink_resolve_uncached);
@@ -3515,7 +3519,7 @@ TRACE_EVENT(xrep_iunlink_relink_prev, ); TRACE_EVENT(xrep_iunlink_add_to_bucket, - TP_PROTO(struct xfs_perag *pag, unsigned int bucket, + TP_PROTO(const struct xfs_perag *pag, unsigned int bucket, xfs_agino_t agino, xfs_agino_t curr_head), TP_ARGS(pag, bucket, agino, curr_head), TP_STRUCT__entry(
@@ -3541,7 +3545,7 @@ TRACE_EVENT(xrep_iunlink_add_to_bucket, ); TRACE_EVENT(xrep_iunlink_commit_bucket, - TP_PROTO(struct xfs_perag *pag, unsigned int bucket, + TP_PROTO(const struct xfs_perag *pag, unsigned int bucket, xfs_agino_t old_agino, xfs_agino_t agino), TP_ARGS(pag, bucket, old_agino, agino), TP_STRUCT__entry(
fs/xfs/xfs_trace.h +10 -9
@@ -181,7 +181,7 @@ TRACE_EVENT(xlog_intent_recovery_failed, ); DECLARE_EVENT_CLASS(xfs_perag_class, - TP_PROTO(struct xfs_perag *pag, unsigned long caller_ip), + TP_PROTO(const struct xfs_perag *pag, unsigned long caller_ip), TP_ARGS(pag, caller_ip), TP_STRUCT__entry( __field(dev_t, dev)
@@ -207,7 +207,7 @@ DECLARE_EVENT_CLASS(xfs_perag_class,#define DEFINE_PERAG_REF_EVENT (name) \ DEFINE_EVENT(xfs_perag_class, name, \ - TP_PROTO(struct xfs_perag *pag, unsigned long caller_ip), \ + TP_PROTO(const struct xfs_perag *pag, unsigned long caller_ip), \ TP_ARGS(pag, caller_ip))DEFINE_PERAG_REF_EVENT (xfs_perag_get);DEFINE_PERAG_REF_EVENT (xfs_perag_hold);
@@ -662,7 +662,7 @@ DEFINE_BUF_ITEM_EVENT(xfs_trans_bhold_release);DEFINE_BUF_ITEM_EVENT (xfs_trans_binval); DECLARE_EVENT_CLASS(xfs_filestream_class, - TP_PROTO(struct xfs_perag *pag, xfs_ino_t ino), + TP_PROTO(const struct xfs_perag *pag, xfs_ino_t ino), TP_ARGS(pag, ino), TP_STRUCT__entry( __field(dev_t, dev)
@@ -684,14 +684,14 @@ DECLARE_EVENT_CLASS(xfs_filestream_class, )#define DEFINE_FILESTREAM_EVENT (name) \ DEFINE_EVENT(xfs_filestream_class, name, \ - TP_PROTO(struct xfs_perag *pag, xfs_ino_t ino), \ + TP_PROTO(const struct xfs_perag *pag, xfs_ino_t ino), \ TP_ARGS(pag, ino))DEFINE_FILESTREAM_EVENT (xfs_filestream_free);DEFINE_FILESTREAM_EVENT (xfs_filestream_lookup);DEFINE_FILESTREAM_EVENT (xfs_filestream_scan); TRACE_EVENT(xfs_filestream_pick, - TP_PROTO(struct xfs_perag *pag, xfs_ino_t ino, xfs_extlen_t free), + TP_PROTO(const struct xfs_perag *pag, xfs_ino_t ino, xfs_extlen_t free), TP_ARGS(pag, ino, free), TP_STRUCT__entry( __field(dev_t, dev)
@@ -1763,8 +1763,9 @@ DEFINE_AGF_EVENT(xfs_agf);DEFINE_AGF_EVENT (xfs_agfl_reset); TRACE_EVENT(xfs_free_extent, - TP_PROTO(struct xfs_perag *pag, xfs_agblock_t agbno, xfs_extlen_t len, - enum xfs_ag_resv_type resv, int haveleft, int haveright), + TP_PROTO(const struct xfs_perag *pag, xfs_agblock_t agbno, + xfs_extlen_t len, enum xfs_ag_resv_type resv, int haveleft, + int haveright), TP_ARGS(pag, agbno, len, resv, haveleft, haveright), TP_STRUCT__entry( __field(dev_t, dev)
@@ -4657,7 +4658,7 @@ TRACE_EVENT(xfs_force_shutdown,#ifdef CONFIG_XFS_DRAIN_INTENTS DECLARE_EVENT_CLASS(xfs_perag_intents_class, - TP_PROTO(struct xfs_perag *pag, void *caller_ip), + TP_PROTO(const struct xfs_perag *pag, void *caller_ip), TP_ARGS(pag, caller_ip), TP_STRUCT__entry( __field(dev_t, dev)
@@ -4680,7 +4681,7 @@ DECLARE_EVENT_CLASS(xfs_perag_intents_class,#define DEFINE_PERAG_INTENTS_EVENT (name) \ DEFINE_EVENT(xfs_perag_intents_class, name, \ - TP_PROTO(struct xfs_perag *pag, void *caller_ip), \ + TP_PROTO(const struct xfs_perag *pag, void *caller_ip), \ TP_ARGS(pag, caller_ip))DEFINE_PERAG_INTENTS_EVENT (xfs_perag_intent_hold);DEFINE_PERAG_INTENTS_EVENT (xfs_perag_intent_rele);
PATCH 14/22 xfs: pass a perag structure to the xfs_ag_resv_init_error trace point
In reply to Darrick J. WongFrom: Christoph Hellwig <[email protected]>
And remove the single instance class indirection for it.
--- fs/xfs/libxfs/xfs_ag_resv.c | 3 +-- fs/xfs/xfs_trace.h | 18 +++++------------- 2 files changed, 6 insertions(+), 15 deletions(-)
fs/xfs/libxfs/xfs_ag_resv.c +1 -2
@@ -206,8 +206,7 @@ __xfs_ag_resv_init(else error =xfs_dec_fdblocks (mp, hidden_space, true);if (error) { -trace_xfs_ag_resv_init_error (pag->pag_mount, pag->pag_agno, - error, _RET_IP_); +trace_xfs_ag_resv_init_error (pag, error, _RET_IP_);xfs_warn (mp,"Per-AG reservation for AG %u failed. Filesystem may run out of space." , pag->pag_agno);
fs/xfs/xfs_trace.h +5 -13
@@ -3144,11 +3144,10 @@ DEFINE_AG_RESV_EVENT(xfs_ag_resv_free_extent);DEFINE_AG_RESV_EVENT (xfs_ag_resv_critical);DEFINE_AG_RESV_EVENT (xfs_ag_resv_needed); -/* simple AG-based error/%ip tracepoint class */ -DECLARE_EVENT_CLASS(xfs_ag_error_class, - TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno, int error, +TRACE_EVENT(xfs_ag_resv_init_error, + TP_PROTO(const struct xfs_perag *pag, int error, unsigned long caller_ip), - TP_ARGS(mp, agno, error, caller_ip), + TP_ARGS(pag, error, caller_ip), TP_STRUCT__entry( __field(dev_t, dev) __field(xfs_agnumber_t, agno)
@@ -3156,8 +3155,8 @@ DECLARE_EVENT_CLASS(xfs_ag_error_class, __field(unsigned long, caller_ip) ),TP_fast_assign ( - __entry->dev = mp->m_super->s_dev; - __entry->agno = agno; + __entry->dev = pag->pag_mount->m_super->s_dev; + __entry->agno = pag->pag_agno; __entry->error = error; __entry->caller_ip = caller_ip; ),
@@ -3168,13 +3167,6 @@ DECLARE_EVENT_CLASS(xfs_ag_error_class, (char *)__entry->caller_ip) ); -#define DEFINE_AG_ERROR_EVENT (name) \ -DEFINE_EVENT(xfs_ag_error_class, name, \ - TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno, int error, \ - unsigned long caller_ip), \ - TP_ARGS(mp, agno, error, caller_ip)) -DEFINE_AG_ERROR_EVENT (xfs_ag_resv_init_error); -/* refcount tracepoint classes */ DECLARE_EVENT_CLASS(xfs_refcount_class,
PATCH 15/22 xfs: pass objects to the xfs_irec_merge_{pre,post} trace points
In reply to Darrick J. WongFrom: Christoph Hellwig <[email protected]>
Pass the perag structure and the irec to these tracepoints so that the decoding is only done when tracing is actually enabled and the call sites look a lot neater.
--- fs/xfs/libxfs/xfs_ialloc.c | 7 ++----- fs/xfs/xfs_trace.h | 33 +++++++++++++++++---------------- 2 files changed, 19 insertions(+), 21 deletions(-)
fs/xfs/libxfs/xfs_ialloc.c +2 -5
@@ -606,15 +606,12 @@ xfs_inobt_insert_sprec( goto error; } -trace_xfs_irec_merge_pre (mp, pag->pag_agno, rec.ir_startino, - rec.ir_holemask, nrec->ir_startino, - nrec->ir_holemask); +trace_xfs_irec_merge_pre (pag, &rec, nrec);/* merge to nrec to output the updated record */ __xfs_inobt_rec_merge (nrec, &rec); -trace_xfs_irec_merge_post (mp, pag->pag_agno, nrec->ir_startino, - nrec->ir_holemask); +trace_xfs_irec_merge_post (pag, nrec); error =xfs_inobt_rec_check_count (mp, nrec);if (error)
fs/xfs/xfs_trace.h +17 -16
@@ -899,9 +899,10 @@ TRACE_EVENT(xfs_iomap_prealloc_size, ) TRACE_EVENT(xfs_irec_merge_pre, - TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno, xfs_agino_t agino, - uint16_t holemask, xfs_agino_t nagino, uint16_t nholemask), - TP_ARGS(mp, agno, agino, holemask, nagino, nholemask), + TP_PROTO(const struct xfs_perag *pag, + const struct xfs_inobt_rec_incore *rec, + const struct xfs_inobt_rec_incore *nrec), + TP_ARGS(pag, rec, nrec), TP_STRUCT__entry( __field(dev_t, dev) __field(xfs_agnumber_t, agno)
@@ -911,12 +912,12 @@ TRACE_EVENT(xfs_irec_merge_pre,__field (uint16_t, nholemask) ),TP_fast_assign ( - __entry->dev = mp->m_super->s_dev; - __entry->agno = agno; - __entry->agino = agino; - __entry->holemask = holemask; - __entry->nagino = nagino; - __entry->nholemask = holemask; + __entry->dev = pag->pag_mount->m_super->s_dev; + __entry->agno = pag->pag_agno; + __entry->agino = rec->ir_startino; + __entry->holemask = rec->ir_holemask; + __entry->nagino = nrec->ir_startino; + __entry->nholemask = nrec->ir_holemask; ), TP_printk("dev %d:%d agno 0x%x agino 0x%x holemask 0x%x new_agino 0x%x new_holemask 0x%x", MAJOR(__entry->dev), MINOR(__entry->dev),
@@ -928,9 +929,9 @@ TRACE_EVENT(xfs_irec_merge_pre, ) TRACE_EVENT(xfs_irec_merge_post, - TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno, xfs_agino_t agino, - uint16_t holemask), - TP_ARGS(mp, agno, agino, holemask), + TP_PROTO(const struct xfs_perag *pag, + const struct xfs_inobt_rec_incore *nrec), + TP_ARGS(pag, nrec), TP_STRUCT__entry( __field(dev_t, dev) __field(xfs_agnumber_t, agno)
@@ -938,10 +939,10 @@ TRACE_EVENT(xfs_irec_merge_post,__field (uint16_t, holemask) ),TP_fast_assign ( - __entry->dev = mp->m_super->s_dev; - __entry->agno = agno; - __entry->agino = agino; - __entry->holemask = holemask; + __entry->dev = pag->pag_mount->m_super->s_dev; + __entry->agno = pag->pag_agno; + __entry->agino = nrec->ir_startino; + __entry->holemask = nrec->ir_holemask; ), TP_printk("dev %d:%d agno 0x%x agino 0x%x holemask 0x%x", MAJOR(__entry->dev),
PATCH 16/22 xfs: pass the iunlink item to the xfs_iunlink_update_dinode trace point
In reply to Darrick J. WongFrom: Christoph Hellwig <[email protected]>
So that decoding is only done when tracing is actually enabled and the call site look a lot neater.
--- fs/xfs/xfs_iunlink_item.c | 13 ++++++------- fs/xfs/xfs_trace.c | 1 + fs/xfs/xfs_trace.h | 15 ++++++++------- 3 files changed, 15 insertions(+), 14 deletions(-)
fs/xfs/xfs_iunlink_item.c +6 -7
@@ -52,14 +52,14 @@ xfs_iunlink_log_dinode(struct xfs_trans *tp, struct xfs_iunlink_item *iup) { - struct xfs_mount *mp = tp->t_mountp; struct xfs_inode *ip = iup->ip;struct xfs_dinode *dip;struct xfs_buf *ibp; +xfs_agino_t old_ptr;int offset;int error; - error =xfs_imap_to_bp (mp, tp, &ip->i_imap, &ibp); + error =xfs_imap_to_bp (tp->t_mountp, tp, &ip->i_imap, &ibp);if (error)return error;/*
@@ -73,22 +73,21 @@ xfs_iunlink_log_dinode( dip =xfs_buf_offset (ibp, ip->i_imap.im_boffset);/* Make sure the old pointer isn't garbage. */ -if (be32_to_cpu (dip->di_next_unlinked) != iup->old_agino) { + old_ptr =be32_to_cpu (dip->di_next_unlinked); +if (old_ptr != iup->old_agino) {xfs_inode_verifier_error (ip, -EFSCORRUPTED , __func__, dip,sizeof (*dip), __this_address); error = -EFSCORRUPTED ; goto out; } -trace_xfs_iunlink_update_dinode (mp, iup->pag->pag_agno, -XFS_INO_TO_AGINO (mp, ip->i_ino), -be32_to_cpu (dip->di_next_unlinked), iup->next_agino); +trace_xfs_iunlink_update_dinode (iup, old_ptr); dip->di_next_unlinked =cpu_to_be32 (iup->next_agino); offset = ip->i_imap.im_boffset + offsetof(struct xfs_dinode , di_next_unlinked); -xfs_dinode_calc_crc (mp, dip); +xfs_dinode_calc_crc (tp->t_mountp, dip);xfs_trans_inode_buf (tp, ibp);xfs_trans_log_buf (tp, ibp, offset, offset +sizeof (xfs_agino_t) -1 );return 0 ;
fs/xfs/xfs_trace.c +1 -0
@@ -32,6 +32,7 @@#include "xfs_fsmap.h" #include "xfs_btree_staging.h" #include "xfs_icache.h" +#include "xfs_iunlink_item.h" #include "xfs_ag.h" #include "xfs_ag_resv.h" #include "xfs_error.h"
fs/xfs/xfs_trace.h +8 -7
@@ -74,6 +74,7 @@ struct xfs_refcount_irec;struct xfs_fsmap ;struct xfs_rmap_irec ;struct xfs_icreate_log ; +struct xfs_iunlink_item ;struct xfs_owner_info ;struct xfs_trans_res ;struct xfs_inobt_rec_incore ;
@@ -4060,9 +4061,8 @@ TRACE_EVENT(xfs_iunlink_update_bucket, ); TRACE_EVENT(xfs_iunlink_update_dinode, - TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno, xfs_agino_t agino, - xfs_agino_t old_ptr, xfs_agino_t new_ptr), - TP_ARGS(mp, agno, agino, old_ptr, new_ptr), + TP_PROTO(const struct xfs_iunlink_item *iup, xfs_agino_t old_ptr), + TP_ARGS(iup, old_ptr), TP_STRUCT__entry( __field(dev_t, dev) __field(xfs_agnumber_t, agno)
@@ -4071,11 +4071,12 @@ TRACE_EVENT(xfs_iunlink_update_dinode,__field (xfs_agino_t, new_ptr) ),TP_fast_assign ( - __entry->dev = mp->m_super->s_dev; - __entry->agno = agno; - __entry->agino = agino; + __entry->dev = iup->pag->pag_mount->m_super->s_dev; + __entry->agno = iup->pag->pag_agno; + __entry->agino = +XFS_INO_TO_AGINO (iup->ip->i_mount, iup->ip->i_ino); __entry->old_ptr = old_ptr; - __entry->new_ptr = new_ptr; + __entry->new_ptr = iup->next_agino; ), TP_printk("dev %d:%d agno 0x%x agino 0x%x old 0x%x new 0x%x", MAJOR(__entry->dev), MINOR(__entry->dev),
PATCH 17/22 xfs: pass objects to the xrep_ibt_walk_rmap tracepoint
In reply to Darrick J. WongFrom: Christoph Hellwig <[email protected]>
Pass the perag structure and the irec so that the decoding is only done when tracing is actually enabled and the call sites look a lot neater, and remove the pointless class indirection.
--- fs/xfs/scrub/ialloc_repair.c | 4 +--- fs/xfs/scrub/trace.h | 29 ++++++++++------------------- 2 files changed, 11 insertions(+), 22 deletions(-)
fs/xfs/scrub/ialloc_repair.c +1 -3
@@ -421,9 +421,7 @@ xrep_ibt_record_inode_blocks(if (error)return error; -trace_xrep_ibt_walk_rmap (mp, ri->sc->sa.pag->pag_agno, - rec->rm_startblock, rec->rm_blockcount, rec->rm_owner, - rec->rm_offset, rec->rm_flags); +trace_xrep_ibt_walk_rmap (ri->sc->sa.pag, rec);/* * Record the free/hole masks for each inode cluster that could be
fs/xfs/scrub/trace.h +10 -19
@@ -1984,11 +1984,9 @@ DEFINE_EVENT(xrep_reap_find_class, name, \DEFINE_REPAIR_REAP_FIND_EVENT (xreap_agextent_select);DEFINE_REPAIR_REAP_FIND_EVENT (xreap_bmapi_select); -DECLARE_EVENT_CLASS(xrep_rmap_class, - TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno, - xfs_agblock_t agbno, xfs_extlen_t len, - uint64_t owner, uint64_t offset, unsigned int flags), - TP_ARGS(mp, agno, agbno, len, owner, offset, flags), +TRACE_EVENT(xrep_ibt_walk_rmap, + TP_PROTO(const struct xfs_perag *pag, const struct xfs_rmap_irec *rec), + TP_ARGS(pag, rec), TP_STRUCT__entry( __field(dev_t, dev) __field(xfs_agnumber_t, agno)
@@ -1999,13 +1997,13 @@ DECLARE_EVENT_CLASS(xrep_rmap_class, __field(unsigned int, flags) ),TP_fast_assign ( - __entry->dev = mp->m_super->s_dev; - __entry->agno = agno; - __entry->agbno = agbno; - __entry->len = len; - __entry->owner = owner; - __entry->offset = offset; - __entry->flags = flags; + __entry->dev = pag->pag_mount->m_super->s_dev; + __entry->agno = pag->pag_agno; + __entry->agbno = rec->rm_startblock; + __entry->len = rec->rm_blockcount; + __entry->owner = rec->rm_owner; + __entry->offset = rec->rm_offset; + __entry->flags = rec->rm_flags; ), TP_printk("dev %d:%d agno 0x%x agbno 0x%x fsbcount 0x%x owner 0x%llx fileoff 0x%llx flags 0x%x", MAJOR(__entry->dev), MINOR(__entry->dev),
@@ -2016,13 +2014,6 @@ DECLARE_EVENT_CLASS(xrep_rmap_class, __entry->offset, __entry->flags) ); -#define DEFINE_REPAIR_RMAP_EVENT (name) \ -DEFINE_EVENT(xrep_rmap_class, name, \ - TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno, \ - xfs_agblock_t agbno, xfs_extlen_t len, \ - uint64_t owner, uint64_t offset, unsigned int flags), \ - TP_ARGS(mp, agno, agbno, len, owner, offset, flags)) -DEFINE_REPAIR_RMAP_EVENT (xrep_ibt_walk_rmap); TRACE_EVENT(xrep_abt_found, TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno,
PATCH 18/22 xfs: pass the pag to the trace_xrep_calc_ag_resblks{,_btsize} trace points
In reply to Darrick J. WongFrom: Christoph Hellwig <[email protected]>
This requires holding the pag refcount a little longer, but allows for the decoding to only happen when tracing is actually enabled, and cleans up the callsites a bit.
--- fs/xfs/scrub/repair.c | 9 ++++----- fs/xfs/scrub/trace.h | 22 +++++++++++----------- 2 files changed, 15 insertions(+), 16 deletions(-)
fs/xfs/scrub/repair.c +4 -5
@@ -331,10 +331,8 @@ xrep_calc_ag_resblks( freelen = aglen; usedlen = aglen; } -xfs_perag_put (pag); -trace_xrep_calc_ag_resblks (mp, sm->sm_agno, icount, aglen, - freelen, usedlen); +trace_xrep_calc_ag_resblks (pag, icount, aglen, freelen, usedlen);/* * Figure out how many blocks we'd need worst case to rebuild
@@ -372,8 +370,9 @@ xrep_calc_ag_resblks( rmapbt_sz =0 ; } -trace_xrep_calc_ag_resblks_btsize (mp, sm->sm_agno, bnobt_sz, - inobt_sz, rmapbt_sz, refcbt_sz); +trace_xrep_calc_ag_resblks_btsize (pag, bnobt_sz, inobt_sz, rmapbt_sz, + refcbt_sz); +xfs_perag_put (pag);return max (max (bnobt_sz, inobt_sz),max (rmapbt_sz, refcbt_sz)); }
fs/xfs/scrub/trace.h +11 -11
@@ -2189,10 +2189,10 @@ TRACE_EVENT(xrep_findroot_block, __entry->level) ) TRACE_EVENT(xrep_calc_ag_resblks, - TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno, - xfs_agino_t icount, xfs_agblock_t aglen, xfs_agblock_t freelen, + TP_PROTO(const struct xfs_perag *pag, xfs_agino_t icount, + xfs_agblock_t aglen, xfs_agblock_t freelen, xfs_agblock_t usedlen), - TP_ARGS(mp, agno, icount, aglen, freelen, usedlen), + TP_ARGS(pag, icount, aglen, freelen, usedlen), TP_STRUCT__entry( __field(dev_t, dev) __field(xfs_agnumber_t, agno)
@@ -2202,8 +2202,8 @@ TRACE_EVENT(xrep_calc_ag_resblks,__field (xfs_agblock_t, usedlen) ),TP_fast_assign ( - __entry->dev = mp->m_super->s_dev; - __entry->agno = agno; + __entry->dev = pag->pag_mount->m_super->s_dev; + __entry->agno = pag->pag_agno; __entry->icount = icount; __entry->aglen = aglen; __entry->freelen = freelen;
@@ -2218,10 +2218,10 @@ TRACE_EVENT(xrep_calc_ag_resblks, __entry->usedlen) ) TRACE_EVENT(xrep_calc_ag_resblks_btsize, - TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno, - xfs_agblock_t bnobt_sz, xfs_agblock_t inobt_sz, - xfs_agblock_t rmapbt_sz, xfs_agblock_t refcbt_sz), - TP_ARGS(mp, agno, bnobt_sz, inobt_sz, rmapbt_sz, refcbt_sz), + TP_PROTO(const struct xfs_perag *pag, xfs_agblock_t bnobt_sz, + xfs_agblock_t inobt_sz, xfs_agblock_t rmapbt_sz, + xfs_agblock_t refcbt_sz), + TP_ARGS(pag, bnobt_sz, inobt_sz, rmapbt_sz, refcbt_sz), TP_STRUCT__entry( __field(dev_t, dev) __field(xfs_agnumber_t, agno)
@@ -2231,8 +2231,8 @@ TRACE_EVENT(xrep_calc_ag_resblks_btsize,__field (xfs_agblock_t, refcbt_sz) ),TP_fast_assign ( - __entry->dev = mp->m_super->s_dev; - __entry->agno = agno; + __entry->dev = pag->pag_mount->m_super->s_dev; + __entry->agno = pag->pag_agno; __entry->bnobt_sz = bnobt_sz; __entry->inobt_sz = inobt_sz; __entry->rmapbt_sz = rmapbt_sz;
PATCH 19/22 xfs: pass the pag to the xrep_newbt_extent_class tracepoints
In reply to Darrick J. WongFrom: Christoph Hellwig <[email protected]>
This requires moving a few of the callsites a little bit to ensure that we already have the reference, but allows for the decoding to only happen when tracing is actually enabled, and cleans up the callsites a bit.
--- fs/xfs/scrub/alloc_repair.c | 8 ++++---- fs/xfs/scrub/newbt.c | 29 +++++++++++++---------------- fs/xfs/scrub/trace.h | 16 +++++++--------- 3 files changed, 24 insertions(+), 29 deletions(-)
fs/xfs/scrub/alloc_repair.c +4 -4
@@ -484,8 +484,8 @@ xrep_abt_reserve_space(ASSERT (arec.ar_blockcount <=UINT_MAX ); len = min_t(unsigned int, arec.ar_blockcount, desired); -trace_xrep_newbt_alloc_ag_blocks (sc->mp, sc->sa.pag->pag_agno, - arec.ar_startblock, len,XFS_RMAP_OWN_AG ); +trace_xrep_newbt_alloc_ag_blocks (sc->sa.pag, arec.ar_startblock, + len,XFS_RMAP_OWN_AG ); error =xrep_newbt_add_extent (&ra->new_bnobt, sc->sa.pag, arec.ar_startblock, len);
@@ -554,8 +554,8 @@ xrep_abt_dispose_one(if (free_aglen ==0 )return 0 ; -trace_xrep_newbt_free_blocks (sc->mp, resv->pag->pag_agno, free_agbno, - free_aglen, ra->new_bnobt.oinfo.oi_owner); +trace_xrep_newbt_free_blocks (resv->pag, free_agbno, free_aglen, + ra->new_bnobt.oinfo.oi_owner); error =__xfs_free_extent (sc->tp, resv->pag, free_agbno, free_aglen, &ra->new_bnobt.oinfo,XFS_AG_RESV_IGNORE , true);
fs/xfs/scrub/newbt.c +13 -16
@@ -250,16 +250,15 @@ xrep_newbt_alloc_ag_blocks(return -ENOSPC ; agno =XFS_FSB_TO_AGNO (mp, args.fsbno); - -trace_xrep_newbt_alloc_ag_blocks (mp, agno, -XFS_FSB_TO_AGBNO (mp, args.fsbno), args.len, - xnr->oinfo.oi_owner); -if (agno != sc->sa.pag->pag_agno) {ASSERT (agno == sc->sa.pag->pag_agno);return -EFSCORRUPTED ; } +trace_xrep_newbt_alloc_ag_blocks (sc->sa.pag, +XFS_FSB_TO_AGBNO (mp, args.fsbno), args.len, + xnr->oinfo.oi_owner); + error =xrep_newbt_add_blocks (xnr, sc->sa.pag, &args);if (error)return error;
@@ -325,16 +324,16 @@ xrep_newbt_alloc_file_blocks( agno =XFS_FSB_TO_AGNO (mp, args.fsbno); -trace_xrep_newbt_alloc_file_blocks (mp, agno, -XFS_FSB_TO_AGBNO (mp, args.fsbno), args.len, - xnr->oinfo.oi_owner); - pag =xfs_perag_get (mp, agno);if (!pag) {ASSERT (0 );return -EFSCORRUPTED ; } +trace_xrep_newbt_alloc_file_blocks (pag, +XFS_FSB_TO_AGBNO (mp, args.fsbno), args.len, + xnr->oinfo.oi_owner); + error =xrep_newbt_add_blocks (xnr, pag, &args);xfs_perag_put (pag);if (error)
@@ -383,8 +382,8 @@ xrep_newbt_free_extent(* space reservation, let the existing EFI free the entire * space extent. */ -trace_xrep_newbt_free_blocks (sc->mp, resv->pag->pag_agno, - free_agbno, free_aglen, xnr->oinfo.oi_owner); +trace_xrep_newbt_free_blocks (resv->pag, free_agbno, free_aglen, + xnr->oinfo.oi_owner);xfs_alloc_commit_autoreap (sc->tp, &resv->autoreap);return 1 ; }
@@ -401,8 +400,8 @@ xrep_newbt_free_extent(if (free_aglen ==0 )return 0 ; -trace_xrep_newbt_free_blocks (sc->mp, resv->pag->pag_agno, free_agbno, - free_aglen, xnr->oinfo.oi_owner); +trace_xrep_newbt_free_blocks (resv->pag, free_agbno, free_aglen, + xnr->oinfo.oi_owner);ASSERT (xnr->resv !=XFS_AG_RESV_AGFL );ASSERT (xnr->resv !=XFS_AG_RESV_IGNORE );
@@ -514,7 +513,6 @@ xrep_newbt_claim_block( union xfs_btree_ptr *ptr) {struct xrep_newbt_resv *resv; -struct xfs_mount *mp = cur->bc_mp;xfs_agblock_t agbno;/*
@@ -539,8 +537,7 @@ xrep_newbt_claim_block(if (resv->used == resv->len)list_move_tail (&resv->list, &xnr->resv_list); -trace_xrep_newbt_claim_block (mp, resv->pag->pag_agno, agbno,1 , - xnr->oinfo.oi_owner); +trace_xrep_newbt_claim_block (resv->pag, agbno,1 , xnr->oinfo.oi_owner);if (cur->bc_ops->ptr_len ==XFS_BTREE_LONG_PTR_LEN ) ptr->l =cpu_to_be64 (xfs_agbno_to_fsb (resv->pag, agbno));
fs/xfs/scrub/trace.h +7 -9
@@ -2272,10 +2272,9 @@ TRACE_EVENT(xrep_reset_counters, ) DECLARE_EVENT_CLASS(xrep_newbt_extent_class, - TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno, - xfs_agblock_t agbno, xfs_extlen_t len, - int64_t owner), - TP_ARGS(mp, agno, agbno, len, owner), + TP_PROTO(const struct xfs_perag *pag, xfs_agblock_t agbno, + xfs_extlen_t len, int64_t owner), + TP_ARGS(pag, agbno, len, owner), TP_STRUCT__entry( __field(dev_t, dev) __field(xfs_agnumber_t, agno)
@@ -2284,8 +2283,8 @@ DECLARE_EVENT_CLASS(xrep_newbt_extent_class,__field (int64_t, owner) ),TP_fast_assign ( - __entry->dev = mp->m_super->s_dev; - __entry->agno = agno; + __entry->dev = pag->pag_mount->m_super->s_dev; + __entry->agno = pag->pag_agno; __entry->agbno = agbno; __entry->len = len; __entry->owner = owner;
@@ -2299,10 +2298,9 @@ DECLARE_EVENT_CLASS(xrep_newbt_extent_class, );#define DEFINE_NEWBT_EXTENT_EVENT (name) \ DEFINE_EVENT(xrep_newbt_extent_class, name, \ - TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno, \ - xfs_agblock_t agbno, xfs_extlen_t len, \ + TP_PROTO(struct xfs_perag *pag, xfs_agblock_t agbno, xfs_extlen_t len, \ int64_t owner), \ - TP_ARGS(mp, agno, agbno, len, owner)) + TP_ARGS(pag, agbno, len, owner))DEFINE_NEWBT_EXTENT_EVENT (xrep_newbt_alloc_ag_blocks);DEFINE_NEWBT_EXTENT_EVENT (xrep_newbt_alloc_file_blocks);DEFINE_NEWBT_EXTENT_EVENT (xrep_newbt_free_blocks);
PATCH 20/22 xfs: convert remaining trace points to pass pag structures
In reply to Darrick J. WongFrom: Christoph Hellwig <[email protected]>
Convert all tracepoints that take [mp,agno] tuples to take a pag argument instead so that decoding only happens when tracepoints are enabled and to clean up the callers.
--- fs/xfs/libxfs/xfs_alloc.c | 4 +- fs/xfs/libxfs/xfs_ialloc.c | 4 +- fs/xfs/libxfs/xfs_inode_util.c | 4 +- fs/xfs/scrub/alloc_repair.c | 2 - fs/xfs/scrub/ialloc.c | 3 - fs/xfs/scrub/ialloc_repair.c | 2 - fs/xfs/scrub/repair.c | 2 - fs/xfs/scrub/rmap_repair.c | 4 +- fs/xfs/scrub/trace.h | 61 ++++++++++++++--------------- fs/xfs/xfs_discard.c | 11 ++--- fs/xfs/xfs_extent_busy.c | 13 ++---- fs/xfs/xfs_health.c | 8 ++-- fs/xfs/xfs_iwalk.c | 2 - fs/xfs/xfs_trace.h | 84 ++++++++++++++++++++-------------------- 14 files changed, 98 insertions(+), 106 deletions(-)
fs/xfs/libxfs/xfs_alloc.c +2 -2
@@ -3360,7 +3360,7 @@ xfs_read_agf(struct xfs_mount *mp = pag->pag_mount;int error; -trace_xfs_read_agf (pag->pag_mount, pag->pag_agno); +trace_xfs_read_agf (pag); error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp, XFS_AG_DADDR(mp, pag->pag_agno, XFS_AGF_DADDR(mp)),
@@ -3391,7 +3391,7 @@ xfs_alloc_read_agf(int error;int allocbt_blks; -trace_xfs_alloc_read_agf (pag->pag_mount, pag->pag_agno); +trace_xfs_alloc_read_agf (pag);/* We don't support trylock when freeing. */ ASSERT((flags & (XFS_ALLOC_FLAG_FREEING | XFS_ALLOC_FLAG_TRYLOCK)) !=
fs/xfs/libxfs/xfs_ialloc.c +2 -2
@@ -2729,7 +2729,7 @@ xfs_read_agi(struct xfs_mount *mp = pag->pag_mount;int error; -trace_xfs_read_agi (pag->pag_mount, pag->pag_agno); +trace_xfs_read_agi (pag); error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp, XFS_AG_DADDR(mp, pag->pag_agno, XFS_AGI_DADDR(mp)),
@@ -2760,7 +2760,7 @@ xfs_ialloc_read_agi(struct xfs_agi *agi;int error; -trace_xfs_ialloc_read_agi (pag->pag_mount, pag->pag_agno); +trace_xfs_ialloc_read_agi (pag); error = xfs_read_agi(pag, tp, (flags & XFS_IALLOC_FLAG_TRYLOCK) ? XBF_TRYLOCK : 0,
fs/xfs/libxfs/xfs_inode_util.c +2 -2
@@ -442,8 +442,8 @@ xfs_iunlink_update_bucket(ASSERT (xfs_verify_agino_or_null (pag, new_agino)); old_value =be32_to_cpu (agi->agi_unlinked[bucket_index]); -trace_xfs_iunlink_update_bucket (tp->t_mountp, pag->pag_agno, bucket_index, - old_value, new_agino); +trace_xfs_iunlink_update_bucket (pag, bucket_index, old_value, + new_agino);/* * We should never find the head of the list already set to the value
fs/xfs/scrub/alloc_repair.c +1 -1
@@ -210,7 +210,7 @@ xrep_abt_stash(if (error)return error; -trace_xrep_abt_found (sc->mp, sc->sa.pag->pag_agno, &arec); +trace_xrep_abt_found (sc->sa.pag, &arec); error =xfarray_append (ra->free_records, &arec);if (error)
fs/xfs/scrub/ialloc.c +1 -2
@@ -367,7 +367,6 @@ xchk_iallocbt_check_cluster(struct xfs_mount *mp = bs->cur->bc_mp;struct xfs_buf *cluster_bp;unsigned int nr_inodes; -xfs_agnumber_t agno = bs->cur->bc_ag.pag->pag_agno;xfs_agblock_t agbno;unsigned int cluster_index;uint16_t cluster_mask =0 ;
@@ -406,7 +405,7 @@ xchk_iallocbt_check_cluster(return 0 ; } - trace_xchk_iallocbt_check_cluster(mp, agno, irec->ir_startino, + trace_xchk_iallocbt_check_cluster(bs->cur->bc_ag.pag, irec->ir_startino, imap.im_blkno, imap.im_len, cluster_base, nr_inodes, cluster_mask, ir_holemask, XFS_INO_TO_OFFSET(mp, irec->ir_startino +
fs/xfs/scrub/ialloc_repair.c +1 -1
@@ -192,7 +192,7 @@ xrep_ibt_stash(if (ri->rie.ir_freecount >0 ) ri->finobt_recs++; -trace_xrep_ibt_found (ri->sc->mp, ri->sc->sa.pag->pag_agno, &ri->rie); +trace_xrep_ibt_found (ri->sc->sa.pag, &ri->rie); error =xfarray_append (ri->inode_records, &ri->rie);if (error)
fs/xfs/scrub/repair.c +1 -1
@@ -611,7 +611,7 @@ xrep_findroot_block(else fab->root =NULLAGBLOCK ; -trace_xrep_findroot_block (mp, ri->sc->sa.pag->pag_agno, agbno, +trace_xrep_findroot_block (ri->sc->sa.pag, agbno,be32_to_cpu (btblock->bb_magic), fab->height -1 ); out:xfs_trans_brelse (ri->sc->tp, bp);
fs/xfs/scrub/rmap_repair.c +2 -2
@@ -231,7 +231,7 @@ xrep_rmap_stash(if (xchk_iscan_aborted (&rr->iscan))return -EFSCORRUPTED ; -trace_xrep_rmap_found (sc->mp, sc->sa.pag->pag_agno, &rmap); +trace_xrep_rmap_found (sc->sa.pag, &rmap);mutex_lock (&rr->lock); mcur =xfs_rmapbt_mem_cursor (sc->sa.pag, sc->tp, &rr->rmap_btree);
@@ -1552,7 +1552,7 @@ xrep_rmapbt_live_update(if (!xrep_rmapbt_want_live_update (&rr->iscan, &p->oinfo)) goto out_unlock; -trace_xrep_rmap_live_update (mp, rr->sc->sa.pag->pag_agno, action, p); +trace_xrep_rmap_live_update (rr->sc->sa.pag, action, p); error =xrep_trans_alloc_hook_dummy (mp, &txcookie, &tp);if (error)
fs/xfs/scrub/trace.h +30 -31
143 lines not on this page · raw message
fs/xfs/xfs_discard.c +5 -6
@@ -117,8 +117,7 @@ xfs_discard_extents(blk_start_plug (&plug);list_for_each_entry (busyp, &extents->extent_list, list) { -trace_xfs_discard_extent (mp, busyp->pag->pag_agno, busyp->bno, - busyp->length); +trace_xfs_discard_extent (busyp->pag, busyp->bno, busyp->length); error = __blkdev_issue_discard(mp->m_ddev_targp->bt_bdev, xfs_agbno_to_daddr(busyp->pag, busyp->bno),
@@ -239,11 +238,11 @@ xfs_trim_gather_extents(* overlapping ranges for now. */ if (fbno + flen < tcur->start) { -trace_xfs_discard_exclude (mp, pag->pag_agno, fbno, flen); +trace_xfs_discard_exclude (pag, fbno, flen); goto next_extent; }if (fbno > tcur->end) { -trace_xfs_discard_exclude (mp, pag->pag_agno, fbno, flen); +trace_xfs_discard_exclude (pag, fbno, flen);if (tcur->by_bno) { tcur->count =0 ;break ;
@@ -261,7 +260,7 @@ xfs_trim_gather_extents(/* Too small? Give up. */ if (flen < tcur->minlen) { -trace_xfs_discard_toosmall (mp, pag->pag_agno, fbno, flen); +trace_xfs_discard_toosmall (pag, fbno, flen);if (tcur->by_bno) goto next_extent; tcur->count =0 ;
@@ -273,7 +272,7 @@ xfs_trim_gather_extents(* discard and try again the next time. */ if (xfs_extent_busy_search (pag, fbno, flen)) { -trace_xfs_discard_busy (mp, pag->pag_agno, fbno, flen); +trace_xfs_discard_busy (pag, fbno, flen); goto next_extent; }
fs/xfs/xfs_extent_busy.c +5 -8
@@ -41,7 +41,7 @@ xfs_extent_busy_insert_list( new->flags = flags;/* trace before insert to be able to see failed inserts */ -trace_xfs_extent_busy (pag->pag_mount, pag->pag_agno, bno, len); +trace_xfs_extent_busy (pag, bno, len);spin_lock (&pag->pagb_lock); rbp = &pag->pagb_tree.rb_node;
@@ -278,13 +278,13 @@ xfs_extent_busy_update_extent(ASSERT (0 ); } -trace_xfs_extent_busy_reuse (pag->pag_mount, pag->pag_agno, fbno, flen); +trace_xfs_extent_busy_reuse (pag, fbno, flen);return true; out_force_log:spin_unlock (&pag->pagb_lock);xfs_log_force (pag->pag_mount,XFS_LOG_SYNC ); -trace_xfs_extent_busy_force (pag->pag_mount, pag->pag_agno, fbno, flen); +trace_xfs_extent_busy_force (pag, fbno, flen);spin_lock (&pag->pagb_lock);return false; }
@@ -496,8 +496,7 @@ xfs_extent_busy_trim( out:if (fbno != *bno || flen != *len) { -trace_xfs_extent_busy_trim (args->mp, args->agno, *bno, *len, - fbno, flen); +trace_xfs_extent_busy_trim (args->pag, *bno, *len, fbno, flen); *bno = fbno; *len = flen; *busy_gen = args->pag->pagb_gen;
@@ -526,9 +525,7 @@ xfs_extent_busy_clear_one( busyp->flags =XFS_EXTENT_BUSY_DISCARDED ;return false; } -trace_xfs_extent_busy_clear (pag->pag_mount, - busyp->pag->pag_agno, busyp->bno, - busyp->length); +trace_xfs_extent_busy_clear (pag, busyp->bno, busyp->length);rb_erase (&busyp->rb_node, &pag->pagb_tree); }
fs/xfs/xfs_health.c +4 -4
@@ -41,7 +41,7 @@ xfs_health_unmount(for_each_perag (mp, agno, pag) {xfs_ag_measure_sickness (pag, &sick, &checked);if (sick) { -trace_xfs_ag_unfixed_corruption (mp, agno, sick); +trace_xfs_ag_unfixed_corruption (pag, sick); warn = true; } }
@@ -233,7 +233,7 @@ xfs_ag_mark_sick( unsigned int mask) {ASSERT (!(mask & ~XFS_SICK_AG_ALL )); -trace_xfs_ag_mark_sick (pag->pag_mount, pag->pag_agno, mask); +trace_xfs_ag_mark_sick (pag, mask);spin_lock (&pag->pag_state_lock); pag->pag_sick |= mask;
@@ -247,7 +247,7 @@ xfs_ag_mark_corrupt( unsigned int mask) {ASSERT (!(mask & ~XFS_SICK_AG_ALL )); -trace_xfs_ag_mark_corrupt (pag->pag_mount, pag->pag_agno, mask); +trace_xfs_ag_mark_corrupt (pag, mask);spin_lock (&pag->pag_state_lock); pag->pag_sick |= mask;
@@ -262,7 +262,7 @@ xfs_ag_mark_healthy( unsigned int mask) {ASSERT (!(mask & ~XFS_SICK_AG_ALL )); -trace_xfs_ag_mark_healthy (pag->pag_mount, pag->pag_agno, mask); +trace_xfs_ag_mark_healthy (pag, mask);spin_lock (&pag->pag_state_lock); pag->pag_sick &= ~mask;
fs/xfs/xfs_iwalk.c +1 -1
@@ -182,7 +182,7 @@ xfs_iwalk_ag_recs(for (i =0 ; i < iwag->nr_recs; i++) {struct xfs_inobt_rec_incore *irec = &iwag->recs[i]; -trace_xfs_iwalk_ag_rec (mp, pag->pag_agno, irec); +trace_xfs_iwalk_ag_rec (pag, irec);if (xfs_pwork_want_abort (&iwag->pwork))return 0 ;
fs/xfs/xfs_trace.h +41 -43
193 lines not on this page · raw message
PATCH 21/22 xfs: split xfs_initialize_perag
In reply to Darrick J. WongFrom: Christoph Hellwig <[email protected]>
Factor out a xfs_perag_alloc helper that allocates a single perag structure.
--- fs/xfs/libxfs/xfs_ag.c | 119 +++++++++++++++++++++++++++--------------------- 1 file changed, 67 insertions(+), 52 deletions(-)
fs/xfs/libxfs/xfs_ag.c +67 -52
@@ -293,6 +293,67 @@ xfs_update_last_ag_size(return 0 ; } +static int +xfs_perag_alloc ( +struct xfs_mount *mp, +xfs_agnumber_t index, +xfs_agnumber_t agcount, +xfs_rfsblock_t dblocks) +{ +struct xfs_perag *pag; +int error; + + pag =kzalloc (sizeof (*pag),GFP_KERNEL ); +if (!pag) +return -ENOMEM ; + + pag->pag_agno = index; + pag->pag_mount = mp; + + error =xa_insert (&mp->m_perags, index, pag,GFP_KERNEL ); +if (error) { +WARN_ON_ONCE (error == -EBUSY ); + goto out_free_pag; + } + +#ifdef __KERNEL__ +/* Place kernel structure only init below this point. */ +spin_lock_init (&pag->pag_ici_lock); +spin_lock_init (&pag->pagb_lock); +spin_lock_init (&pag->pag_state_lock); +INIT_DELAYED_WORK (&pag->pag_blockgc_work, xfs_blockgc_worker); +INIT_RADIX_TREE (&pag->pag_ici_root,GFP_ATOMIC ); +xfs_defer_drain_init (&pag->pag_intents_drain); +init_waitqueue_head (&pag->pagb_wait); + pag->pagb_tree =RB_ROOT ; +xfs_hooks_init (&pag->pag_rmap_update_hooks); +#endif /* __KERNEL__ */ + + error =xfs_buf_cache_init (&pag->pag_bcache); +if (error) + goto out_remove_pag; + +/* Active ref owned by mount indicates AG is online. */ +atomic_set (&pag->pag_active_ref,1 ); + +/* +* Pre-calculated geometry +*/ + pag->block_count =__xfs_ag_block_count (mp, index, agcount, dblocks); + pag->min_block =XFS_AGFL_BLOCK (mp); +__xfs_agino_range (mp, pag->block_count, &pag->agino_min, + &pag->agino_max); + +return 0 ; + +out_remove_pag: +xfs_defer_drain_free (&pag->pag_intents_drain); + pag =xa_erase (&mp->m_perags, index); +out_free_pag: +kfree (pag); +return error; +} + int xfs_initialize_perag( struct xfs_mount *mp,
@@ -301,68 +362,22 @@ xfs_initialize_perag(xfs_rfsblock_t dblocks, xfs_agnumber_t *maxagi) { - struct xfs_perag *pag; xfs_agnumber_t index;int error; +if (orig_agcount >= new_agcount) +return 0 ; +for (index = orig_agcount; index < new_agcount; index++) { - pag =kzalloc (sizeof (*pag),GFP_KERNEL ); -if (!pag) { - error = -ENOMEM ; + error =xfs_perag_alloc (mp, index, new_agcount, dblocks); +if (error) goto out_unwind_new_pags; - } - pag->pag_agno = index; - pag->pag_mount = mp; - - error =xa_insert (&mp->m_perags, index, pag,GFP_KERNEL ); -if (error) { -WARN_ON_ONCE (error == -EBUSY ); - goto out_free_pag; - } - -#ifdef __KERNEL__ -/* Place kernel structure only init below this point. */ -spin_lock_init (&pag->pag_ici_lock); -spin_lock_init (&pag->pagb_lock); -spin_lock_init (&pag->pag_state_lock); -INIT_DELAYED_WORK (&pag->pag_blockgc_work, xfs_blockgc_worker); -INIT_RADIX_TREE (&pag->pag_ici_root,GFP_ATOMIC ); -xfs_defer_drain_init (&pag->pag_intents_drain); -init_waitqueue_head (&pag->pagb_wait); - pag->pagb_tree =RB_ROOT ; -xfs_hooks_init (&pag->pag_rmap_update_hooks); -#endif /* __KERNEL__ */ - - error =xfs_buf_cache_init (&pag->pag_bcache); -if (error) - goto out_remove_pag; - -/* Active ref owned by mount indicates AG is online. */ -atomic_set (&pag->pag_active_ref,1 ); - -/* -* Pre-calculated geometry -*/ - pag->block_count =__xfs_ag_block_count (mp, index, new_agcount, - dblocks); - pag->min_block =XFS_AGFL_BLOCK (mp); -__xfs_agino_range (mp, pag->block_count, &pag->agino_min, - &pag->agino_max); } - index =xfs_set_inode_alloc (mp, new_agcount); - -if (maxagi) - *maxagi = index; - + *maxagi =xfs_set_inode_alloc (mp, new_agcount); mp->m_ag_prealloc_blocks =xfs_prealloc_blocks (mp);return 0 ; -out_remove_pag: -xfs_defer_drain_free (&pag->pag_intents_drain); - pag =xa_erase (&mp->m_perags, index); -out_free_pag: -kfree (pag); out_unwind_new_pags:xfs_free_perag_range (mp, orig_agcount, index);return error;
PATCH 22/22 xfs: insert the pag structures into the xarray later
In reply to Darrick J. WongFrom: Christoph Hellwig <[email protected]>
Cleaning up is much easier if a structure can't be looked up yet, so only insert the pag once it is fully set up.
--- fs/xfs/libxfs/xfs_ag.c | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-)
fs/xfs/libxfs/xfs_ag.c +15 -16
@@ -307,15 +307,6 @@ xfs_perag_alloc(if (!pag)return -ENOMEM ; - pag->pag_agno = index; - pag->pag_mount = mp; - - error =xa_insert (&mp->m_perags, index, pag,GFP_KERNEL ); -if (error) { -WARN_ON_ONCE (error == -EBUSY ); - goto out_free_pag; - } -#ifdef __KERNEL__/* Place kernel structure only init below this point. */ spin_lock_init (&pag->pag_ici_lock);
@@ -331,10 +322,7 @@ xfs_perag_alloc( error =xfs_buf_cache_init (&pag->pag_bcache);if (error) - goto out_remove_pag; - -/* Active ref owned by mount indicates AG is online. */ -atomic_set (&pag->pag_active_ref,1 ); + goto out_defer_drain_free;/* * Pre-calculated geometry
@@ -344,12 +332,23 @@ xfs_perag_alloc(__xfs_agino_range (mp, pag->block_count, &pag->agino_min, &pag->agino_max); + pag->pag_agno = index; + pag->pag_mount = mp; +/* Active ref owned by mount indicates AG is online. */ +atomic_set (&pag->pag_active_ref,1 ); + + error =xa_insert (&mp->m_perags, index, pag,GFP_KERNEL ); +if (error) { +WARN_ON_ONCE (error == -EBUSY ); + goto out_buf_cache_destroy; + } +return 0 ; -out_remove_pag: +out_buf_cache_destroy: +xfs_buf_cache_destroy (&pag->pag_bcache); +out_defer_drain_free:xfs_defer_drain_free (&pag->pag_intents_drain); - pag =xa_erase (&mp->m_perags, index); -out_free_pag:kfree (pag);return error; }
PATCH 2/9 xfs: create a generic allocation group structure
In reply to Darrick J. WongHi all,
Soon we'll be sharding the realtime volume into separate allocation groups. These rt groups will /mostly/ behave the same as the ones on the data device, but since rt groups don't have quite the same set of struct fields as perags, let's hoist the parts that will be shared by both into a common xfs_group object.
If you're going to start using this code, I strongly recommend pulling from my git trees, which are linked below.
This has been running on the djcloud for months with no problems. Enjoy! Comments and questions are, as always, welcome.
--D
kernel git tree:
https://git.kernel.org/cgit/linux/kernel/git/djwong/xfs-linux.git/log/?h=generic-groups
xfsprogs git tree:
https://git.kernel.org/cgit/linux/kernel/git/djwong/xfsprogs-dev.git/log/?h=generic-groups
---
Commits in this patchset:
* xfs: factor out a xfs_iwalk_args helper
* xfs: factor out a generic xfs_group structure
* xfs: add a xfs_group_next_range helper
* xfs: switch perag iteration from the for_each macros to a while based iterator
* xfs: move metadata health tracking to the generic group structure
* xfs: mark xfs_perag_intent_{hold,rele} static
* xfs: move draining of deferred operations to the generic group structure
* xfs: move the online repair rmap hooks to the generic group structure
* xfs: return the busy generation from xfs_extent_busy_list_empty
* xfs: convert extent busy tracepoints to the generic group structure
* xfs: convert busy extent tracking to the generic group structure
* xfs: add a generic group pointer to the btree cursor
* xfs: store a generic xfs_group pointer in xfs_getfsmap_info
* xfs: add group based bno conversion helpers
* xfs: remove xfs_group_intent_hold and xfs_group_intent_rele
* xfs: store a generic group structure in the intents
--- fs/xfs/Makefile | 1 fs/xfs/libxfs/xfs_ag.c | 149 ++++------------------- fs/xfs/libxfs/xfs_ag.h | 165 ++++++++++++++----------- fs/xfs/libxfs/xfs_ag_resv.c | 19 ++- fs/xfs/libxfs/xfs_alloc.c | 74 ++++++----- fs/xfs/libxfs/xfs_alloc.h | 2 fs/xfs/libxfs/xfs_alloc_btree.c | 30 ++--- fs/xfs/libxfs/xfs_bmap.c | 2 fs/xfs/libxfs/xfs_bmap.h | 2 fs/xfs/libxfs/xfs_btree.c | 37 ++---- fs/xfs/libxfs/xfs_btree.h | 3 fs/xfs/libxfs/xfs_btree_mem.c | 6 - fs/xfs/libxfs/xfs_group.c | 225 ++++++++++++++++++++++++++++++++++ fs/xfs/libxfs/xfs_group.h | 131 ++++++++++++++++++++ fs/xfs/libxfs/xfs_health.h | 45 +++---- fs/xfs/libxfs/xfs_ialloc.c | 50 ++++---- fs/xfs/libxfs/xfs_ialloc_btree.c | 27 ++-- fs/xfs/libxfs/xfs_refcount.c | 26 ++-- fs/xfs/libxfs/xfs_refcount.h | 2 fs/xfs/libxfs/xfs_refcount_btree.c | 14 +- fs/xfs/libxfs/xfs_rmap.c | 42 +++--- fs/xfs/libxfs/xfs_rmap.h | 6 - fs/xfs/libxfs/xfs_rmap_btree.c | 28 ++-- fs/xfs/libxfs/xfs_sb.c | 28 ++-- fs/xfs/libxfs/xfs_types.c | 5 - fs/xfs/libxfs/xfs_types.h | 8 + fs/xfs/scrub/agheader_repair.c | 22 ++- fs/xfs/scrub/alloc.c | 2 fs/xfs/scrub/alloc_repair.c | 12 +- fs/xfs/scrub/bmap.c | 8 + fs/xfs/scrub/bmap_repair.c | 9 + fs/xfs/scrub/common.c | 4 - fs/xfs/scrub/common.h | 3 fs/xfs/scrub/cow_repair.c | 9 + fs/xfs/scrub/fscounters.c | 10 +- fs/xfs/scrub/health.c | 21 +-- fs/xfs/scrub/ialloc.c | 14 +- fs/xfs/scrub/ialloc_repair.c | 2 fs/xfs/scrub/inode_repair.c | 5 - fs/xfs/scrub/iscan.c | 4 - fs/xfs/scrub/newbt.c | 8 + fs/xfs/scrub/reap.c | 2 fs/xfs/scrub/refcount.c | 3 fs/xfs/scrub/repair.c | 4 - fs/xfs/scrub/rmap.c | 4 - fs/xfs/scrub/rmap_repair.c | 16 +- fs/xfs/scrub/trace.h | 82 ++++++------ fs/xfs/xfs_bmap_item.c | 5 - fs/xfs/xfs_discard.c | 20 ++- fs/xfs/xfs_drain.c | 78 +++++------- fs/xfs/xfs_drain.h | 22 +-- fs/xfs/xfs_extent_busy.c | 201 ++++++++++++++++++------------ fs/xfs/xfs_extent_busy.h | 59 +++------ fs/xfs/xfs_extfree_item.c | 14 +- fs/xfs/xfs_filestream.c | 8 + fs/xfs/xfs_fsmap.c | 49 ++++--- fs/xfs/xfs_fsops.c | 10 +- fs/xfs/xfs_health.c | 99 +++++++-------- fs/xfs/xfs_icache.c | 60 +++------ fs/xfs/xfs_inode.c | 6 - fs/xfs/xfs_iwalk.c | 99 ++++++--------- fs/xfs/xfs_iwalk.h | 7 - fs/xfs/xfs_log_recover.c | 11 +- fs/xfs/xfs_mount.h | 36 +++++ fs/xfs/xfs_refcount_item.c | 9 + fs/xfs/xfs_reflink.c | 7 - fs/xfs/xfs_rmap_item.c | 9 + fs/xfs/xfs_super.c | 11 +- fs/xfs/xfs_trace.c | 1 fs/xfs/xfs_trace.h | 238 ++++++++++++++++++++++-------------- 70 files changed, 1380 insertions(+), 1050 deletions(-) create mode 100644 fs/xfs/libxfs/xfs_group.c create mode 100644 fs/xfs/libxfs/xfs_group.h
PATCH 1/16 xfs: factor out a xfs_iwalk_args helper
From: Christoph Hellwig <[email protected]>
Add a helper to share more code between xfs_iwalk and xfs_inobt_walk, and at the same time do away with the extra flags indirect so that everyone use the same names for the same flags when using the common iwalk code.
--- fs/xfs/xfs_iwalk.c | 83 ++++++++++++++++++++-------------------------------- fs/xfs/xfs_iwalk.h | 7 +--- 2 files changed, 33 insertions(+), 57 deletions(-)
fs/xfs/xfs_iwalk.c +32 -51
@@ -534,6 +534,35 @@ xfs_iwalk_prefetch(return max (inobt_records,2U ); } +static int +xfs_iwalk_args ( +struct xfs_iwalk_ag *iwag, +unsigned int flags) +{ +struct xfs_mount *mp = iwag->mp; +xfs_agnumber_t agno =XFS_INO_TO_AGNO (mp, iwag->startino); +int error; + +ASSERT (agno < mp->m_sb.sb_agcount); +ASSERT (!(flags & ~XFS_IWALK_FLAGS_ALL )); + + error =xfs_iwalk_alloc (iwag); +if (error) +return error; + +for_each_perag_from (mp, agno, iwag->pag) { + error =xfs_iwalk_ag (iwag); +if (error || (flags &XFS_IWALK_SAME_AG )) { +xfs_perag_rele (iwag->pag); +break ; + } + iwag->startino =XFS_AGINO_TO_INO (mp, agno +1 ,0 ); + } + +xfs_iwalk_free (iwag); +return error; +} +/* * Walk all inodes in the filesystem starting from @startino. The @iwalk_fn * will be called for each allocated inode, being passed the inode's number and
@@ -562,32 +591,8 @@ xfs_iwalk( .pwork = XFS_PWORK_SINGLE_THREADED, .lastino = NULLFSINO, }; -struct xfs_perag *pag; -xfs_agnumber_t agno =XFS_INO_TO_AGNO (mp, startino); -int error; -ASSERT (agno < mp->m_sb.sb_agcount); -ASSERT (!(flags & ~XFS_IWALK_FLAGS_ALL )); - - error =xfs_iwalk_alloc (&iwag); -if (error) -return error; - -for_each_perag_from (mp, agno, pag) { - iwag.pag = pag; - error =xfs_iwalk_ag (&iwag); -if (error) -break ; - iwag.startino =XFS_AGINO_TO_INO (mp, agno +1 ,0 ); -if (flags &XFS_INOBT_WALK_SAME_AG ) -break ; - iwag.pag =NULL ; - } - -if (iwag.pag) -xfs_perag_rele (pag); -xfs_iwalk_free (&iwag); -return error; +return xfs_iwalk_args (&iwag, flags); }/* Run per-thread iwalk work. */
@@ -673,7 +678,7 @@ xfs_iwalk_threaded( iwag->lastino =NULLFSINO ;xfs_pwork_queue (&pctl, &iwag->pwork); startino =XFS_AGINO_TO_INO (mp, pag->pag_agno +1 ,0 ); -if (flags &XFS_INOBT_WALK_SAME_AG ) +if (flags &XFS_IWALK_SAME_AG )break ; }if (pag)
@@ -747,30 +752,6 @@ xfs_inobt_walk( .pwork = XFS_PWORK_SINGLE_THREADED, .lastino = NULLFSINO, }; -struct xfs_perag *pag; -xfs_agnumber_t agno =XFS_INO_TO_AGNO (mp, startino); -int error; -ASSERT (agno < mp->m_sb.sb_agcount); -ASSERT (!(flags & ~XFS_INOBT_WALK_FLAGS_ALL )); - - error =xfs_iwalk_alloc (&iwag); -if (error) -return error; - -for_each_perag_from (mp, agno, pag) { - iwag.pag = pag; - error =xfs_iwalk_ag (&iwag); -if (error) -break ; - iwag.startino =XFS_AGINO_TO_INO (mp, pag->pag_agno +1 ,0 ); -if (flags &XFS_INOBT_WALK_SAME_AG ) -break ; - iwag.pag =NULL ; - } - -if (iwag.pag) -xfs_perag_rele (pag); -xfs_iwalk_free (&iwag); -return error; +return xfs_iwalk_args (&iwag, flags); }
fs/xfs/xfs_iwalk.h +1 -6
@@ -25,7 +25,7 @@ int xfs_iwalk_threaded(struct xfs_mount *mp, xfs_ino_t startino, unsigned int flags, xfs_iwalk_fn iwalk_fn, unsigned int inode_records, bool poll, void *data); -/* Only iterate inodes within the same AG as @startino. */ +/* Only iterate within the same AG as @startino. */ #define XFS_IWALK_SAME_AG (1U << 0)#define XFS_IWALK_FLAGS_ALL (XFS_IWALK_SAME_AG)
@@ -41,9 +41,4 @@ int xfs_inobt_walk(struct xfs_mount *mp, struct xfs_trans *tp, xfs_inobt_walk_fn inobt_walk_fn, unsigned int inobt_records, void *data); -/* Only iterate inobt records within the same AG as @startino. */ -#define XFS_INOBT_WALK_SAME_AG (XFS_IWALK_SAME_AG) - -#define XFS_INOBT_WALK_FLAGS_ALL (XFS_INOBT_WALK_SAME_AG) -#endif /* __XFS_IWALK_H__ */
PATCH 2/16 xfs: factor out a generic xfs_group structure
In reply to Darrick J. WongFrom: Christoph Hellwig <[email protected]>
Split the lookup and refcount handling of struct xfs_perag into an embedded xfs_group structure that can be reused for the upcoming realtime groups.
It will be extended with more features later.
Note that he xg_type field will only need a single bit even with realtime group support. For now it fills a hole, but it might be worth to fold it into another field if we can use this space better.
--- fs/xfs/Makefile | 1 fs/xfs/libxfs/xfs_ag.c | 139 ++++++------------------------ fs/xfs/libxfs/xfs_ag.h | 81 ++++++++++++++--- fs/xfs/libxfs/xfs_ag_resv.c | 19 ++-- fs/xfs/libxfs/xfs_alloc.c | 39 ++++---- fs/xfs/libxfs/xfs_alloc_btree.c | 2 fs/xfs/libxfs/xfs_bmap.c | 2 fs/xfs/libxfs/xfs_btree.c | 6 + fs/xfs/libxfs/xfs_group.c | 169 ++++++++++++++++++++++++++++++++++++ fs/xfs/libxfs/xfs_group.h | 41 +++++++++ fs/xfs/libxfs/xfs_ialloc.c | 40 ++++----- fs/xfs/libxfs/xfs_ialloc_btree.c | 16 ++- fs/xfs/libxfs/xfs_refcount.c | 4 - fs/xfs/libxfs/xfs_refcount_btree.c | 8 +- fs/xfs/libxfs/xfs_rmap.c | 4 - fs/xfs/libxfs/xfs_rmap_btree.c | 7 + fs/xfs/libxfs/xfs_sb.c | 6 + fs/xfs/libxfs/xfs_types.h | 8 ++ fs/xfs/scrub/agheader_repair.c | 22 ++--- fs/xfs/scrub/alloc_repair.c | 2 fs/xfs/scrub/common.h | 3 - fs/xfs/scrub/ialloc_repair.c | 2 fs/xfs/scrub/iscan.c | 4 - fs/xfs/scrub/newbt.c | 8 +- fs/xfs/scrub/repair.c | 4 - fs/xfs/scrub/rmap.c | 2 fs/xfs/scrub/rmap_repair.c | 10 +- fs/xfs/scrub/trace.h | 82 +++++++++-------- fs/xfs/xfs_discard.c | 4 - fs/xfs/xfs_extent_busy.c | 4 - fs/xfs/xfs_extfree_item.c | 2 fs/xfs/xfs_filestream.c | 8 +- fs/xfs/xfs_fsmap.c | 12 +-- fs/xfs/xfs_icache.c | 55 ++++-------- fs/xfs/xfs_inode.c | 6 + fs/xfs/xfs_iwalk.c | 6 + fs/xfs/xfs_log_recover.c | 6 + fs/xfs/xfs_mount.h | 6 + fs/xfs/xfs_refcount_item.c | 2 fs/xfs/xfs_reflink.c | 2 fs/xfs/xfs_rmap_item.c | 2 fs/xfs/xfs_super.c | 11 +- fs/xfs/xfs_trace.c | 1 fs/xfs/xfs_trace.h | 149 ++++++++++++++++++++------------ 44 files changed, 608 insertions(+), 399 deletions(-) create mode 100644 fs/xfs/libxfs/xfs_group.c create mode 100644 fs/xfs/libxfs/xfs_group.h
fs/xfs/Makefile +1 -0
@@ -14,6 +14,7 @@ xfs-y += xfs_trace.o # build the libxfs code first xfs-y += $(addprefix libxfs/, \ + xfs_group.o \ xfs_ag.o \ xfs_alloc.o \ xfs_alloc_btree.o \
fs/xfs/libxfs/xfs_ag.c +27 -112
205 lines not on this page · raw message
fs/xfs/libxfs/xfs_ag.h +65 -16
139 lines not on this page · raw message
fs/xfs/libxfs/xfs_ag_resv.c +10 -9
@@ -70,6 +70,7 @@ xfs_ag_resv_critical(struct xfs_perag *pag, enum xfs_ag_resv_type type) { + struct xfs_mount *mp = pag_mount(pag);xfs_extlen_t avail;xfs_extlen_t orig;
@@ -92,8 +93,8 @@ xfs_ag_resv_critical(/* Critically low if less than 10% or max btree height remains. */ return XFS_TEST_ERROR (avail < orig /10 || - avail < pag->pag_mount->m_agbtree_maxlevels, - pag->pag_mount,XFS_ERRTAG_AG_RESV_CRITICAL ); + avail < mp->m_agbtree_maxlevels, + mp,XFS_ERRTAG_AG_RESV_CRITICAL ); }/*
@@ -137,8 +138,8 @@ __xfs_ag_resv_free(trace_xfs_ag_resv_free (pag, type,0 ); resv =xfs_perag_resv (pag, type); -if (pag->pag_agno ==0 ) - pag->pag_mount->m_ag_max_usable += resv->ar_asked; +if (pag_agno (pag) ==0 ) +pag_mount (pag)->m_ag_max_usable += resv->ar_asked;/* * RMAPBT blocks come from the AGFL and AGFL blocks are always * considered "free", so whatever was reserved at mount time must be
@@ -148,7 +149,7 @@ __xfs_ag_resv_free( oldresv = resv->ar_orig_reserved; else oldresv = resv->ar_reserved; -xfs_add_fdblocks (pag->pag_mount, oldresv); +xfs_add_fdblocks (pag_mount (pag), oldresv); resv->ar_reserved =0 ; resv->ar_asked =0 ; resv->ar_orig_reserved =0 ;
@@ -170,7 +171,7 @@ __xfs_ag_resv_init( xfs_extlen_t ask, xfs_extlen_t used) { -struct xfs_mount *mp = pag->pag_mount; +struct xfs_mount *mp =pag_mount (pag);struct xfs_ag_resv *resv;int error;xfs_extlen_t hidden_space;
@@ -209,7 +210,7 @@ __xfs_ag_resv_init(trace_xfs_ag_resv_init_error (pag, error, _RET_IP_);xfs_warn (mp,"Per-AG reservation for AG %u failed. Filesystem may run out of space." , - pag->pag_agno); +pag_agno (pag));return error; }
@@ -219,7 +220,7 @@ __xfs_ag_resv_init(* counter, we only make the adjustment for AG 0. This assumes that * there aren't any AGs hungrier for per-AG reservation than AG 0. */ -if (pag->pag_agno ==0 ) +if (pag_agno (pag) ==0 ) mp->m_ag_max_usable -= ask; resv =xfs_perag_resv (pag, type);
@@ -237,7 +238,7 @@ xfs_ag_resv_init(struct xfs_perag *pag, struct xfs_trans *tp) { - struct xfs_mount *mp = pag->pag_mount; + struct xfs_mount *mp = pag_mount(pag);xfs_extlen_t ask;xfs_extlen_t used;int error =0 , error2;
fs/xfs/libxfs/xfs_alloc.c +19 -20
@@ -275,7 +275,7 @@ xfs_alloc_complain_bad_rec(xfs_warn (mp,"%sbt record corruption in AG %d detected at %pS!" , - cur->bc_ops->name, cur->bc_ag.pag->pag_agno, fa); + cur->bc_ops->name,pag_agno (cur->bc_ag.pag), fa);xfs_warn (mp,"start block 0x%x block count 0x%x" , irec->ar_startblock, irec->ar_blockcount);
@@ -799,7 +799,7 @@ xfs_agfl_verify(* use it by using uncached buffers that don't have the perag attached * so we can detect and avoid this problem. */ -if (bp->b_pag &&be32_to_cpu (agfl->agfl_seqno) != bp->b_pag->pag_agno) +if (bp->b_pag &&be32_to_cpu (agfl->agfl_seqno) !=pag_agno ((bp->b_pag)))return __this_address;for (i =0 ; i <xfs_agfl_size (mp); i++) {
@@ -879,13 +879,12 @@ xfs_alloc_read_agfl(struct xfs_trans *tp, struct xfs_buf **bpp) { - struct xfs_mount *mp = pag->pag_mount; + struct xfs_mount *mp = pag_mount(pag);struct xfs_buf *bp;int error; - error =xfs_trans_read_buf ( - mp, tp, mp->m_ddev_targp, -XFS_AG_DADDR (mp, pag->pag_agno,XFS_AGFL_DADDR (mp)), + error =xfs_trans_read_buf (mp, tp, mp->m_ddev_targp, +XFS_AG_DADDR (mp,pag_agno (pag),XFS_AGFL_DADDR (mp)),XFS_FSS_TO_BB (mp,1 ),0 , &bp, &xfs_agfl_buf_ops);if (xfs_metadata_is_sick (error))xfs_ag_mark_sick (pag,XFS_SICK_AG_AGFL );
@@ -2428,7 +2427,7 @@ xfs_alloc_longest_free_extent(* reservations and AGFL rules in place, we can return this extent. */ if (pag->pagf_longest > delta) -return min_t (xfs_extlen_t, pag->pag_mount->m_ag_max_usable, +return min_t (xfs_extlen_t,pag_mount (pag)->m_ag_max_usable, pag->pagf_longest - delta);/* Otherwise, let the caller try for 1 block if there's space. */
@@ -2611,7 +2610,7 @@ xfs_agfl_reset(xfs_warn (mp,"WARNING: Reset corrupted AGFL on AG %u. %d blocks leaked. " "Please unmount and run xfs_repair." , - pag->pag_agno, pag->pagf_flcount); +pag_agno (pag), pag->pagf_flcount); agf->agf_flfirst =0 ; agf->agf_fllast =cpu_to_be32 (xfs_agfl_size (mp) -1 );
@@ -3188,7 +3187,7 @@ xfs_validate_ag_length(* use it by using uncached buffers that don't have the perag attached * so we can detect and avoid this problem. */ -if (bp->b_pag && seqno != bp->b_pag->pag_agno) +if (bp->b_pag && seqno !=pag_agno (bp->b_pag))return __this_address;/*
@@ -3357,13 +3356,13 @@ xfs_read_agf(int flags, struct xfs_buf **agfbpp) { - struct xfs_mount *mp = pag->pag_mount; + struct xfs_mount *mp = pag_mount(pag);int error;trace_xfs_read_agf (pag); error =xfs_trans_read_buf (mp, tp, mp->m_ddev_targp, -XFS_AG_DADDR (mp, pag->pag_agno,XFS_AGF_DADDR (mp)), +XFS_AG_DADDR (mp,pag_agno (pag),XFS_AGF_DADDR (mp)),XFS_FSS_TO_BB (mp,1 ), flags, agfbpp, &xfs_agf_buf_ops);if (xfs_metadata_is_sick (error))xfs_ag_mark_sick (pag,XFS_SICK_AG_AGF );
@@ -3386,6 +3385,7 @@ xfs_alloc_read_agf(int flags, struct xfs_buf **agfbpp) { + struct xfs_mount *mp = pag_mount(pag);struct xfs_buf *agfbp;struct xfs_agf *agf;int error;
@@ -3412,7 +3412,7 @@ xfs_alloc_read_agf( pag->pagf_cnt_level =be32_to_cpu (agf->agf_cnt_level); pag->pagf_rmap_level =be32_to_cpu (agf->agf_rmap_level); pag->pagf_refcount_level =be32_to_cpu (agf->agf_refcount_level); -if (xfs_agfl_needs_reset (pag->pag_mount, agf)) +if (xfs_agfl_needs_reset (mp, agf))set_bit (XFS_AGSTATE_AGFL_NEEDS_RESET , &pag->pag_opstate);else clear_bit (XFS_AGSTATE_AGFL_NEEDS_RESET , &pag->pag_opstate);
@@ -3425,16 +3425,15 @@ xfs_alloc_read_agf(* counter only tracks non-root blocks. */ allocbt_blks = pag->pagf_btreeblks; -if (xfs_has_rmapbt (pag->pag_mount)) +if (xfs_has_rmapbt (mp)) allocbt_blks -=be32_to_cpu (agf->agf_rmap_blocks) -1 ;if (allocbt_blks >0 ) -atomic64_add (allocbt_blks, - &pag->pag_mount->m_allocbt_blks); +atomic64_add (allocbt_blks, &mp->m_allocbt_blks);set_bit (XFS_AGSTATE_AGF_INIT , &pag->pag_opstate); }#ifdef DEBUG - else if (!xfs_is_shutdown(pag->pag_mount)) { + else if (!xfs_is_shutdown(mp)) {ASSERT (pag->pagf_freeblks ==be32_to_cpu (agf->agf_freeblks));ASSERT (pag->pagf_btreeblks ==be32_to_cpu (agf->agf_btreeblks));ASSERT (pag->pagf_flcount ==be32_to_cpu (agf->agf_flcount));
@@ -3652,7 +3651,7 @@ xfs_alloc_vextent_this_ag(int error;ASSERT (args->pag !=NULL ); -ASSERT (args->pag->pag_agno == agno); +ASSERT (pag_agno (args->pag) == agno); args->agno = agno; args->agbno =0 ;
@@ -3865,7 +3864,7 @@ xfs_alloc_vextent_exact_bno(int error;ASSERT (args->pag !=NULL ); -ASSERT (args->pag->pag_agno ==XFS_FSB_TO_AGNO (mp, target)); +ASSERT (pag_agno (args->pag) ==XFS_FSB_TO_AGNO (mp, target)); args->agno =XFS_FSB_TO_AGNO (mp, target); args->agbno =XFS_FSB_TO_AGBNO (mp, target);
@@ -3904,7 +3903,7 @@ xfs_alloc_vextent_near_bno(int error;if (!needs_perag) -ASSERT (args->pag->pag_agno ==XFS_FSB_TO_AGNO (mp, target)); +ASSERT (pag_agno (args->pag) ==XFS_FSB_TO_AGNO (mp, target)); args->agno =XFS_FSB_TO_AGNO (mp, target); args->agbno =XFS_FSB_TO_AGBNO (mp, target);
@@ -3941,7 +3940,7 @@ xfs_free_extent_fix_freelist(memset (&args,0 ,sizeof (struct xfs_alloc_arg )); args.tp = tp; args.mp = tp->t_mountp; - args.agno = pag->pag_agno; + args.agno =pag_agno (pag); args.pag = pag;/*
fs/xfs/libxfs/xfs_alloc_btree.c +1 -1
@@ -178,7 +178,7 @@ xfs_allocbt_init_ptr_from_cur( {struct xfs_agf *agf = cur->bc_ag.agbp->b_addr; -ASSERT (cur->bc_ag.pag->pag_agno ==be32_to_cpu (agf->agf_seqno)); +ASSERT (pag_agno (cur->bc_ag.pag) ==be32_to_cpu (agf->agf_seqno));if (xfs_btree_is_bno (cur->bc_ops)) ptr->s = agf->agf_bno_root;
fs/xfs/libxfs/xfs_bmap.c +1 -1
@@ -3280,7 +3280,7 @@ xfs_bmap_longest_free_extent( } longest =xfs_alloc_longest_free_extent (pag, -xfs_alloc_min_freelist (pag->pag_mount, pag), +xfs_alloc_min_freelist (pag_mount (pag), pag),xfs_ag_resv_needed (pag,XFS_AG_RESV_NONE ));if (*blen < longest) *blen = longest;
fs/xfs/libxfs/xfs_btree.c +3 -3
@@ -372,7 +372,7 @@ xfs_btree_check_ptr(case XFS_BTREE_TYPE_AG :xfs_err (cur->bc_mp,"AG %u: Corrupt %sbt pointer at level %d index %d." , - cur->bc_ag.pag->pag_agno, cur->bc_ops->name, +pag_agno (cur->bc_ag.pag), cur->bc_ops->name, level, index);break ; }
@@ -1312,7 +1312,7 @@ xfs_btree_owner(case XFS_BTREE_TYPE_INODE :return cur->bc_ino.ip->i_ino;case XFS_BTREE_TYPE_AG : -return cur->bc_ag.pag->pag_agno; +return pag_agno (cur->bc_ag.pag);default :ASSERT (0 );return 0 ;
@@ -4744,7 +4744,7 @@ xfs_btree_agblock_v5hdr_verify(return __this_address;if (block->bb_u.s.bb_blkno !=cpu_to_be64 (xfs_buf_daddr (bp)))return __this_address; -if (pag &&be32_to_cpu (block->bb_u.s.bb_owner) != pag->pag_agno) +if (pag &&be32_to_cpu (block->bb_u.s.bb_owner) !=pag_agno (pag))return __this_address;return NULL ; }
fs/xfs/libxfs/xfs_group.c new file +169 -0
169 lines not on this page · raw message
fs/xfs/libxfs/xfs_group.h new file +41 -0
41 lines not on this page · raw message
fs/xfs/libxfs/xfs_ialloc.c +20 -20
@@ -142,7 +142,7 @@ xfs_inobt_complain_bad_rec(xfs_warn (mp,"%sbt record corruption in AG %d detected at %pS!" , - cur->bc_ops->name, cur->bc_ag.pag->pag_agno, fa); + cur->bc_ops->name,pag_agno (cur->bc_ag.pag), fa); xfs_warn(mp, "start inode 0x%x, count 0x%x, free 0x%x freemask 0x%llx, holemask 0x%x", irec->ir_startino, irec->ir_count, irec->ir_freecount,
@@ -551,7 +551,7 @@ xfs_inobt_insert_sprec(struct xfs_buf *agbp, struct xfs_inobt_rec_incore *nrec) /* in/out: new/merged rec. */ { - struct xfs_mount *mp = pag->pag_mount; + struct xfs_mount *mp = pag_mount(pag);struct xfs_btree_cur *cur;int error;int i;
@@ -645,7 +645,7 @@ xfs_finobt_insert_sprec(struct xfs_buf *agbp, struct xfs_inobt_rec_incore *nrec) /* in/out: new rec. */ { - struct xfs_mount *mp = pag->pag_mount; + struct xfs_mount *mp = pag_mount(pag);struct xfs_btree_cur *cur;int error;int i;
@@ -880,7 +880,7 @@ xfs_ialloc_ag_alloc(* rather than a linear progression to prevent the next generation * number from being easily guessable. */ - error =xfs_ialloc_inode_init (args.mp, tp,NULL , newlen, pag->pag_agno, + error =xfs_ialloc_inode_init (args.mp, tp,NULL , newlen,pag_agno (pag), args.agbno, args.len,get_random_u32 ());if (error)
@@ -1071,7 +1071,7 @@ xfs_dialloc_check_ino(if (error)return -EAGAIN ; - error =xfs_imap_to_bp (pag->pag_mount, tp, &imap, &bp); + error =xfs_imap_to_bp (pag_mount (pag), tp, &imap, &bp);if (error)return -EAGAIN ;
@@ -1122,7 +1122,7 @@ xfs_dialloc_ag_inobt(/* * If in the same AG as the parent, try to get near the parent. */ -if (pagno == pag->pag_agno) { +if (pagno ==pag_agno (pag)) {int doneleft;/* done, to the left */ int doneright;/* done, to the right */
@@ -1599,7 +1599,7 @@ xfs_dialloc_ag(* parent. If so, find the closest available inode to the parent. If * not, consider the agi hint or find the first free inode in the AG. */ -if (pag->pag_agno == pagno) +if (pag_agno (pag) == pagno) error =xfs_dialloc_ag_finobt_near (pagino, &cur, &rec);else error =xfs_dialloc_ag_finobt_newino (agi, cur, &rec);
@@ -2053,7 +2053,7 @@ xfs_difree_inobt(struct xfs_icluster *xic, struct xfs_inobt_rec_incore *orec) { - struct xfs_mount *mp = pag->pag_mount; + struct xfs_mount *mp = pag_mount(pag);struct xfs_agi *agi = agbp->b_addr;struct xfs_btree_cur *cur;struct xfs_inobt_rec_incore rec;
@@ -2187,7 +2187,7 @@ xfs_difree_finobt(xfs_agino_t agino, struct xfs_inobt_rec_incore *ibtrec) /* inobt record */ { - struct xfs_mount *mp = pag->pag_mount; + struct xfs_mount *mp = pag_mount(pag);struct xfs_btree_cur *cur;struct xfs_inobt_rec_incore rec;int offset = agino - ibtrec->ir_startino;
@@ -2310,9 +2310,9 @@ xfs_difree(/* * Break up inode number into its components. */ -if (pag->pag_agno !=XFS_INO_TO_AGNO (mp, inode)) { -xfs_warn (mp,"%s: agno != pag->pag_agno (%d != %d)." , - __func__,XFS_INO_TO_AGNO (mp, inode), pag->pag_agno); +if (pag_agno (pag) !=XFS_INO_TO_AGNO (mp, inode)) { +xfs_warn (mp,"%s: agno != pag_agno(pag) (%d != %d)." , + __func__,XFS_INO_TO_AGNO (mp, inode),pag_agno (pag));ASSERT (0 );return -EINVAL ; }
@@ -2373,7 +2373,7 @@ xfs_imap_lookup( xfs_agblock_t *offset_agbno, int flags) { -struct xfs_mount *mp = pag->pag_mount; +struct xfs_mount *mp =pag_mount (pag);struct xfs_inobt_rec_incore rec;struct xfs_btree_cur *cur;struct xfs_buf *agbp;
@@ -2384,7 +2384,7 @@ xfs_imap_lookup(if (error) {xfs_alert (mp,"%s: xfs_ialloc_read_agi() returned error %d, agno %d" , - __func__, error, pag->pag_agno); + __func__, error,pag_agno (pag));return error; }
@@ -2434,7 +2434,7 @@ xfs_imap( struct xfs_imap *imap, /* location map structure */ uint flags) /* flags for inode btree lookup */ { -struct xfs_mount *mp = pag->pag_mount; +struct xfs_mount *mp =pag_mount (pag);xfs_agblock_t agbno;/* block number of inode in the alloc group */ xfs_agino_t agino;/* inode number within alloc group */ xfs_agblock_t chunk_agbno;/* first block in inode chunk */
@@ -2726,13 +2726,13 @@ xfs_read_agi(xfs_buf_flags_t flags, struct xfs_buf **agibpp) { - struct xfs_mount *mp = pag->pag_mount; + struct xfs_mount *mp = pag_mount(pag);int error;trace_xfs_read_agi (pag); error =xfs_trans_read_buf (mp, tp, mp->m_ddev_targp, -XFS_AG_DADDR (mp, pag->pag_agno,XFS_AGI_DADDR (mp)), +XFS_AG_DADDR (mp,pag_agno (pag),XFS_AGI_DADDR (mp)),XFS_FSS_TO_BB (mp,1 ), flags, agibpp, &xfs_agi_buf_ops);if (xfs_metadata_is_sick (error))xfs_ag_mark_sick (pag,XFS_SICK_AG_AGI );
@@ -2780,7 +2780,7 @@ xfs_ialloc_read_agi(* we are in the middle of a forced shutdown. */ ASSERT (pag->pagi_freecount ==be32_to_cpu (agi->agi_freecount) || -xfs_is_shutdown (pag->pag_mount)); +xfs_is_shutdown (pag_mount (pag)));if (agibpp) *agibpp = agibp;else
@@ -3119,13 +3119,13 @@ xfs_ialloc_check_shrink(int has;int error; -if (!xfs_has_sparseinodes (pag->pag_mount)) +if (!xfs_has_sparseinodes (pag_mount (pag)))return 0 ; cur =xfs_inobt_init_cursor (pag, tp, agibp);/* Look up the inobt record that would correspond to the new EOFS. */ - agino =XFS_AGB_TO_AGINO (pag->pag_mount, new_length); + agino =XFS_AGB_TO_AGINO (pag_mount (pag), new_length); error =xfs_inobt_lookup (cur, agino,XFS_LOOKUP_LE , &has);if (error || !has) goto out;
fs/xfs/libxfs/xfs_ialloc_btree.c +8 -8
@@ -248,7 +248,7 @@ xfs_inobt_init_ptr_from_cur( {struct xfs_agi *agi = cur->bc_ag.agbp->b_addr; -ASSERT (cur->bc_ag.pag->pag_agno ==be32_to_cpu (agi->agi_seqno)); +ASSERT (pag_agno (cur->bc_ag.pag) ==be32_to_cpu (agi->agi_seqno)); ptr->s = agi->agi_root; }
@@ -260,7 +260,7 @@ xfs_finobt_init_ptr_from_cur( {struct xfs_agi *agi = cur->bc_ag.agbp->b_addr; -ASSERT (cur->bc_ag.pag->pag_agno ==be32_to_cpu (agi->agi_seqno)); +ASSERT (pag_agno (cur->bc_ag.pag) ==be32_to_cpu (agi->agi_seqno)); ptr->s = agi->agi_free_root; }
@@ -478,7 +478,7 @@ xfs_inobt_init_cursor(struct xfs_trans *tp, struct xfs_buf *agbp) { - struct xfs_mount *mp = pag->pag_mount; + struct xfs_mount *mp = pag_mount(pag);struct xfs_btree_cur *cur; cur = xfs_btree_alloc_cursor(mp, tp, &xfs_inobt_ops,
@@ -504,7 +504,7 @@ xfs_finobt_init_cursor(struct xfs_trans *tp, struct xfs_buf *agbp) { - struct xfs_mount *mp = pag->pag_mount; + struct xfs_mount *mp = pag_mount(pag);struct xfs_btree_cur *cur; cur = xfs_btree_alloc_cursor(mp, tp, &xfs_finobt_ops,
@@ -715,7 +715,7 @@ static xfs_extlen_txfs_inobt_max_size ( struct xfs_perag *pag) { -struct xfs_mount *mp = pag->pag_mount; +struct xfs_mount *mp =pag_mount (pag);xfs_agblock_t agblocks = pag->block_count;/* Bail out if we're uninitialized, which can happen in mkfs. */
@@ -727,7 +727,7 @@ xfs_inobt_max_size(* never be available for the kinds of things that would require btree * expansion. We therefore can pretend the space isn't there. */ -if (xfs_ag_contains_log (mp, pag->pag_agno)) +if (xfs_ag_contains_log (mp,pag_agno (pag))) agblocks -= mp->m_sb.sb_logblocks; return xfs_btree_calc_size(M_IGEO(mp)->inobt_mnr,
@@ -791,10 +791,10 @@ xfs_finobt_calc_reserves(xfs_extlen_t tree_len =0 ;int error; -if (!xfs_has_finobt (pag->pag_mount)) +if (!xfs_has_finobt (pag_mount (pag)))return 0 ; -if (xfs_has_inobtcounts (pag->pag_mount)) +if (xfs_has_inobtcounts (pag_mount (pag))) error =xfs_finobt_read_blocks (pag, tp, &tree_len);else error =xfs_finobt_count_blocks (pag, tp, &tree_len);
fs/xfs/libxfs/xfs_refcount.c +2 -2
@@ -154,7 +154,7 @@ xfs_refcount_complain_bad_rec(xfs_warn (mp,"Refcount BTree record corruption in AG %d detected at %pS!" , - cur->bc_ag.pag->pag_agno, fa); +pag_agno (cur->bc_ag.pag), fa);xfs_warn (mp,"Start block 0x%x, block count 0x%x, references 0x%x" , irec->rc_startblock, irec->rc_blockcount, irec->rc_refcount);
@@ -1321,7 +1321,7 @@ xfs_refcount_continue_op( ri->ri_startblock =xfs_agbno_to_fsb (pag, new_agbno);ASSERT (xfs_verify_fsbext (mp, ri->ri_startblock, ri->ri_blockcount)); -ASSERT (pag->pag_agno ==XFS_FSB_TO_AGNO (mp, ri->ri_startblock)); +ASSERT (pag_agno (pag) ==XFS_FSB_TO_AGNO (mp, ri->ri_startblock));return 0 ; }
fs/xfs/libxfs/xfs_refcount_btree.c +4 -4
@@ -81,7 +81,7 @@ xfs_refcountbt_alloc_block( *stat =0 ;return 0 ; } -ASSERT (args.agno == cur->bc_ag.pag->pag_agno); +ASSERT (args.agno ==pag_agno (cur->bc_ag.pag));ASSERT (args.len ==1 ); new->s =cpu_to_be32 (args.agbno);
@@ -169,7 +169,7 @@ xfs_refcountbt_init_ptr_from_cur( {struct xfs_agf *agf = cur->bc_ag.agbp->b_addr; -ASSERT (cur->bc_ag.pag->pag_agno ==be32_to_cpu (agf->agf_seqno)); +ASSERT (pag_agno (cur->bc_ag.pag) ==be32_to_cpu (agf->agf_seqno)); ptr->s = agf->agf_refcount_root; }
@@ -361,7 +361,7 @@ xfs_refcountbt_init_cursor( {struct xfs_btree_cur *cur; -ASSERT (pag->pag_agno < mp->m_sb.sb_agcount); +ASSERT (pag_agno (pag) < mp->m_sb.sb_agcount); cur =xfs_btree_alloc_cursor (mp, tp, &xfs_refcountbt_ops, mp->m_refc_maxlevels, xfs_refcountbt_cur_cache);
@@ -514,7 +514,7 @@ xfs_refcountbt_calc_reserves(* never be available for the kinds of things that would require btree * expansion. We therefore can pretend the space isn't there. */ -if (xfs_ag_contains_log (mp, pag->pag_agno)) +if (xfs_ag_contains_log (mp,pag_agno (pag))) agblocks -= mp->m_sb.sb_logblocks; *ask +=xfs_refcountbt_max_size (mp, agblocks);
fs/xfs/libxfs/xfs_rmap.c +2 -2
@@ -213,7 +213,7 @@ xfs_rmap_check_irec(struct xfs_perag *pag, const struct xfs_rmap_irec *irec) { - struct xfs_mount *mp = pag->pag_mount; + struct xfs_mount *mp = pag_mount(pag);bool is_inode;bool is_unwritten;bool is_bmbt;
@@ -288,7 +288,7 @@ xfs_rmap_complain_bad_rec(else xfs_warn (mp,"Reverse Mapping BTree record corruption in AG %d detected at %pS!" , - cur->bc_ag.pag->pag_agno, fa); +pag_agno (cur->bc_ag.pag), fa); xfs_warn(mp, "Owner 0x%llx, flags 0x%x, start block 0x%x block count 0x%x", irec->rm_owner, irec->rm_flags, irec->rm_startblock,
fs/xfs/libxfs/xfs_rmap_btree.c +3 -4
@@ -227,7 +227,7 @@ xfs_rmapbt_init_ptr_from_cur( {struct xfs_agf *agf = cur->bc_ag.agbp->b_addr; -ASSERT (cur->bc_ag.pag->pag_agno ==be32_to_cpu (agf->agf_seqno)); +ASSERT (pag_agno (cur->bc_ag.pag) ==be32_to_cpu (agf->agf_seqno)); ptr->s = agf->agf_rmap_root; }
@@ -647,9 +647,8 @@ xfs_rmapbt_mem_cursor( struct xfbtree *xfbt) {struct xfs_btree_cur *cur; -struct xfs_mount *mp = pag->pag_mount; - cur =xfs_btree_alloc_cursor (mp, tp, &xfs_rmapbt_mem_ops, + cur =xfs_btree_alloc_cursor (pag_mount (pag), tp, &xfs_rmapbt_mem_ops,xfs_rmapbt_maxlevels_ondisk (), xfs_rmapbt_cur_cache); cur->bc_mem.xfbtree = xfbt; cur->bc_nlevels = xfbt->nlevels;
@@ -863,7 +862,7 @@ xfs_rmapbt_calc_reserves(* never be available for the kinds of things that would require btree * expansion. We therefore can pretend the space isn't there. */ -if (xfs_ag_contains_log (mp, pag->pag_agno)) +if (xfs_ag_contains_log (mp,pag_agno (pag))) agblocks -= mp->m_sb.sb_logblocks;/* Reserve 1% of the AG or enough for 1 block per record. */
fs/xfs/libxfs/xfs_sb.c +3 -3
@@ -1120,7 +1120,7 @@ xfs_update_secondary_sbs(struct xfs_buf *bp; error =xfs_buf_get (mp->m_ddev_targp, -XFS_AG_DADDR (mp, pag->pag_agno,XFS_SB_DADDR ), +XFS_AG_DADDR (mp,pag_agno (pag),XFS_SB_DADDR ),XFS_FSS_TO_BB (mp,1 ), &bp);/* * If we get an error reading or writing alternate superblocks,
@@ -1132,7 +1132,7 @@ xfs_update_secondary_sbs(if (error) {xfs_warn (mp,"error allocating secondary superblock for ag %d" , - pag->pag_agno); +pag_agno (pag));if (!saved_error) saved_error = error;continue ;
@@ -1153,7 +1153,7 @@ xfs_update_secondary_sbs(if (error) {xfs_warn (mp,"write error %d updating a secondary superblock near ag %d" , - error, pag->pag_agno); + error,pag_agno (pag));if (!saved_error) saved_error = error;continue ;
fs/xfs/libxfs/xfs_types.h +8 -0
@@ -212,6 +212,14 @@ enum xbtree_recpacking { XBTREE_RECPACKING_FULL, }; +enum xfs_group_type { +XG_TYPE_AG , +XG_TYPE_MAX , +} __packed; + +#define XG_TYPE_STRINGS \ + { XG_TYPE_AG, "ag" } +/* * Type verifier functions */
fs/xfs/scrub/agheader_repair.c +11 -11
@@ -208,7 +208,7 @@ xrep_agf_init_header(memset (agf,0 ,BBTOB (agf_bp->b_length)); agf->agf_magicnum =cpu_to_be32 (XFS_AGF_MAGIC ); agf->agf_versionnum =cpu_to_be32 (XFS_AGF_VERSION ); - agf->agf_seqno =cpu_to_be32 (pag->pag_agno); + agf->agf_seqno =cpu_to_be32 (pag_agno (pag)); agf->agf_length =cpu_to_be32 (pag->block_count); agf->agf_flfirst = old_agf->agf_flfirst; agf->agf_fllast = old_agf->agf_fllast;
@@ -384,7 +384,7 @@ xrep_agf(* was corrupt after xfs_alloc_read_agf failed with -EFSCORRUPTED. */ error =xfs_trans_read_buf (mp, sc->tp, mp->m_ddev_targp, -XFS_AG_DADDR (mp, sc->sa.pag->pag_agno, +XFS_AG_DADDR (mp,pag_agno (sc->sa.pag),XFS_AGF_DADDR (mp)),XFS_FSS_TO_BB (mp,1 ),0 , &agf_bp,NULL );if (error)
@@ -687,7 +687,7 @@ xrep_agfl_init_header( agfl =XFS_BUF_TO_AGFL (agfl_bp);memset (agfl,0xFF ,BBTOB (agfl_bp->b_length)); agfl->agfl_magicnum =cpu_to_be32 (XFS_AGFL_MAGIC ); - agfl->agfl_seqno =cpu_to_be32 (sc->sa.pag->pag_agno); + agfl->agfl_seqno =cpu_to_be32 (pag_agno (sc->sa.pag));uuid_copy (&agfl->agfl_uuid, &mp->m_sb.sb_meta_uuid);/*
@@ -741,7 +741,7 @@ xrep_agfl(* was corrupt after xfs_alloc_read_agfl failed with -EFSCORRUPTED. */ error =xfs_trans_read_buf (mp, sc->tp, mp->m_ddev_targp, -XFS_AG_DADDR (mp, sc->sa.pag->pag_agno, +XFS_AG_DADDR (mp,pag_agno (sc->sa.pag),XFS_AGFL_DADDR (mp)),XFS_FSS_TO_BB (mp,1 ),0 , &agfl_bp,NULL );if (error)
@@ -897,7 +897,7 @@ xrep_agi_init_header(memset (agi,0 ,BBTOB (agi_bp->b_length)); agi->agi_magicnum =cpu_to_be32 (XFS_AGI_MAGIC ); agi->agi_versionnum =cpu_to_be32 (XFS_AGI_VERSION ); - agi->agi_seqno =cpu_to_be32 (pag->pag_agno); + agi->agi_seqno =cpu_to_be32 (pag_agno (pag)); agi->agi_length =cpu_to_be32 (pag->block_count); agi->agi_newino =cpu_to_be32 (NULLAGINO ); agi->agi_dirino =cpu_to_be32 (NULLAGINO );
@@ -1112,9 +1112,9 @@ xrep_iunlink_igrab(struct xfs_perag *pag, struct xfs_inode *ip) { - struct xfs_mount *mp = pag->pag_mount; + struct xfs_mount *mp = pag_mount(pag); -if (XFS_INO_TO_AGNO (mp, ip->i_ino) != pag->pag_agno) +if (XFS_INO_TO_AGNO (mp, ip->i_ino) !=pag_agno (pag))return false;if (!xfs_inode_on_unlinked_list (ip))
@@ -1138,7 +1138,7 @@ xrep_iunlink_visit(unsigned int bucket;int error; -ASSERT (XFS_INO_TO_AGNO (mp, ip->i_ino) == ragi->sc->sa.pag->pag_agno); +ASSERT (XFS_INO_TO_AGNO (mp, ip->i_ino) ==pag_agno (ragi->sc->sa.pag));ASSERT (xfs_inode_on_unlinked_list (ip)); agino =XFS_INO_TO_AGINO (mp, ip->i_ino);
@@ -1169,7 +1169,7 @@ xrep_iunlink_mark_incore( struct xrep_agi *ragi) {struct xfs_perag *pag = ragi->sc->sa.pag; -struct xfs_mount *mp = pag->pag_mount; +struct xfs_mount *mp =pag_mount (pag);uint32_t first_index =0 ;bool done = false;unsigned int nr_found =0 ;
@@ -1209,7 +1209,7 @@ xrep_iunlink_mark_incore(* us to see this inode, so another lookup from the * same index will not find it again. */ -if (XFS_INO_TO_AGNO (mp, ip->i_ino) != pag->pag_agno) +if (XFS_INO_TO_AGNO (mp, ip->i_ino) !=pag_agno (pag))continue ; first_index =XFS_INO_TO_AGINO (mp, ip->i_ino +1 );if (first_index <XFS_INO_TO_AGINO (mp, ip->i_ino))
@@ -1761,7 +1761,7 @@ xrep_agi(* was corrupt after xfs_ialloc_read_agi failed with -EFSCORRUPTED. */ error =xfs_trans_read_buf (mp, sc->tp, mp->m_ddev_targp, -XFS_AG_DADDR (mp, sc->sa.pag->pag_agno, +XFS_AG_DADDR (mp,pag_agno (sc->sa.pag),XFS_AGI_DADDR (mp)),XFS_FSS_TO_BB (mp,1 ),0 , &ragi->agi_bp,NULL );if (error)
fs/xfs/scrub/alloc_repair.c +1 -1
@@ -543,7 +543,7 @@ xrep_abt_dispose_one(/* Add a deferred rmap for each extent we used. */ if (resv->used >0 ) -xfs_rmap_alloc_extent (sc->tp, pag->pag_agno, resv->agbno, +xfs_rmap_alloc_extent (sc->tp,pag_agno (pag), resv->agbno, resv->used,XFS_RMAP_OWN_AG );/*
fs/xfs/scrub/common.h +2 -1
@@ -216,7 +216,8 @@ int xchk_metadata_inode_forks(struct xfs_scrub *sc);#define xchk_xfile_ag_descr (sc, fmt, ...) \ kasprintf(XCHK_GFP_FLAGS, "XFS (%s): AG 0x%x " fmt, \ (sc)->mp->m_super->s_id, \ - (sc)->sa.pag ? (sc)->sa.pag->pag_agno : (sc)->sm->sm_agno, \ + (sc)->sa.pag ? \ + pag_agno((sc)->sa.pag) : (sc)->sm->sm_agno, \ ##__VA_ARGS__)#define xchk_xfile_ino_descr (sc, fmt, ...) \ kasprintf(XCHK_GFP_FLAGS, "XFS (%s): inode 0x%llx " fmt, \
fs/xfs/scrub/ialloc_repair.c +1 -1
@@ -814,7 +814,7 @@ xrep_iallocbt( sc->sick_mask =XFS_SICK_AG_INOBT |XFS_SICK_AG_FINOBT ;/* Set up enough storage to handle an AG with nothing but inodes. */ -xfs_agino_range (mp, sc->sa.pag->pag_agno, &first_agino, &last_agino); +xfs_agino_range (mp,pag_agno (sc->sa.pag), &first_agino, &last_agino); last_agino /=XFS_INODES_PER_CHUNK ; descr =xchk_xfile_ag_descr (sc,"inode index records" ); error = xfarray_create(descr, last_agino,
fs/xfs/scrub/iscan.c +2 -2
@@ -67,7 +67,7 @@ xchk_iscan_mask_skipino(xfs_agnumber_t skip_agno =XFS_INO_TO_AGNO (mp, iscan->skip_ino);xfs_agnumber_t skip_agino =XFS_INO_TO_AGINO (mp, iscan->skip_ino); -if (pag->pag_agno != skip_agno) +if (pag_agno (pag) != skip_agno)return ;if (skip_agino < rec->ir_startino)return ;
@@ -95,7 +95,7 @@ xchk_iscan_find_next(struct xfs_btree_cur *cur;struct xfs_mount *mp = sc->mp;struct xfs_trans *tp = sc->tp; -xfs_agnumber_t agno = pag->pag_agno; +xfs_agnumber_t agno =pag_agno (pag);xfs_agino_t lastino =NULLAGINO ;xfs_agino_t first, last;xfs_agino_t agino = *cursor;
fs/xfs/scrub/newbt.c +4 -4
@@ -58,7 +58,7 @@ xrep_newbt_estimate_slack(if (sc->ops->type ==ST_PERAG ) { free = sc->sa.pag->pagf_freeblks; - sz =xfs_ag_block_count (sc->mp, sc->sa.pag->pag_agno); + sz =xfs_ag_block_count (sc->mp,pag_agno (sc->sa.pag)); }else { free =percpu_counter_sum (&sc->mp->m_fdblocks); sz = sc->mp->m_sb.sb_dblocks;
@@ -205,7 +205,7 @@ xrep_newbt_validate_ag_alloc_hint(struct xfs_scrub *sc = xnr->sc;xfs_agnumber_t agno =XFS_FSB_TO_AGNO (sc->mp, xnr->alloc_hint); -if (agno == sc->sa.pag->pag_agno && +if (agno ==pag_agno (sc->sa.pag) &&xfs_verify_fsbno (sc->mp, xnr->alloc_hint))return ;
@@ -250,8 +250,8 @@ xrep_newbt_alloc_ag_blocks(return -ENOSPC ; agno =XFS_FSB_TO_AGNO (mp, args.fsbno); -if (agno != sc->sa.pag->pag_agno) { -ASSERT (agno == sc->sa.pag->pag_agno); +if (agno !=pag_agno (sc->sa.pag)) { +ASSERT (agno ==pag_agno (sc->sa.pag));return -EFSCORRUPTED ; }
fs/xfs/scrub/repair.c +2 -2
@@ -413,7 +413,7 @@ xrep_fix_freelist( args.mp = sc->mp; args.tp = sc->tp; - args.agno = sc->sa.pag->pag_agno; + args.agno =pag_agno (sc->sa.pag); args.alignment =1 ; args.pag = sc->sa.pag;
@@ -972,7 +972,7 @@ xrep_reset_perag_resv(if (error == -ENOSPC ) {xfs_err (sc->mp,"Insufficient free space to reset per-AG reservation for AG %u after repair." , - sc->sa.pag->pag_agno); +pag_agno (sc->sa.pag)); error =0 ; }
fs/xfs/scrub/rmap.c +1 -1
@@ -410,7 +410,7 @@ xchk_rmapbt_walk_ag_metadata( goto out;/* OWN_LOG: Internal log */ -if (xfs_ag_contains_log (mp, sc->sa.pag->pag_agno)) { +if (xfs_ag_contains_log (mp,pag_agno (sc->sa.pag))) { error =xagb_bitmap_set (&cr->log_owned,XFS_FSB_TO_AGBNO (mp, mp->m_sb.sb_logstart), mp->m_sb.sb_logblocks);
fs/xfs/scrub/rmap_repair.c +5 -5
@@ -344,7 +344,7 @@ xrep_rmap_visit_bmbt(int error;if (XFS_FSB_TO_AGNO (mp, rec->br_startblock) != - rf->rr->sc->sa.pag->pag_agno) +pag_agno (rf->rr->sc->sa.pag))return 0 ; agbno =XFS_FSB_TO_AGBNO (mp, rec->br_startblock);
@@ -391,7 +391,7 @@ xrep_rmap_visit_iroot_btree_block(return 0 ; fsbno =XFS_DADDR_TO_FSB (cur->bc_mp,xfs_buf_daddr (bp)); -if (XFS_FSB_TO_AGNO (cur->bc_mp, fsbno) != rf->rr->sc->sa.pag->pag_agno) +if (XFS_FSB_TO_AGNO (cur->bc_mp, fsbno) !=pag_agno (rf->rr->sc->sa.pag))return 0 ; agbno =XFS_FSB_TO_AGBNO (cur->bc_mp, fsbno);
@@ -801,7 +801,7 @@ xrep_rmap_find_log_rmaps( {struct xfs_scrub *sc = rr->sc; -if (!xfs_ag_contains_log (sc->mp, sc->sa.pag->pag_agno)) +if (!xfs_ag_contains_log (sc->mp,pag_agno (sc->sa.pag)))return 0 ; return xrep_rmap_stash(rr,
@@ -976,7 +976,7 @@ xrep_rmap_try_reserve( {struct xrep_rmap_agfl ra = { .bitmap = freesp_blocks, - .agno = rr->sc->sa.pag->pag_agno, + .agno =pag_agno (rr->sc->sa.pag), };struct xfs_scrub *sc = rr->sc;struct xrep_newbt_resv *resv, *n;
@@ -1596,7 +1596,7 @@ xrep_rmap_setup_scan(/* Set up in-memory rmap btree */ error =xfs_rmapbt_mem_init (sc->mp, &rr->rmap_btree, sc->xmbtp, - sc->sa.pag->pag_agno); +pag_agno (sc->sa.pag));if (error) goto out_mutex;
fs/xfs/scrub/trace.h +41 -41
202 lines not on this page · raw message
fs/xfs/xfs_discard.c +2 -2
@@ -159,7 +159,7 @@ xfs_trim_gather_extents(struct xfs_trim_cur *tcur, struct xfs_busy_extents *extents) { - struct xfs_mount *mp = pag->pag_mount; + struct xfs_mount *mp = pag_mount(pag);struct xfs_trans *tp;struct xfs_btree_cur *cur;struct xfs_buf *agbp;
@@ -365,7 +365,7 @@ xfs_trim_perag_extents(* list after this function call, as it may have been freed by * the time control returns to us. */ - error =xfs_discard_extents (pag->pag_mount, extents); + error =xfs_discard_extents (pag_mount (pag), extents);if (error)break ;
fs/xfs/xfs_extent_busy.c +2 -2
@@ -283,7 +283,7 @@ xfs_extent_busy_update_extent( out_force_log:spin_unlock (&pag->pagb_lock); -xfs_log_force (pag->pag_mount,XFS_LOG_SYNC ); +xfs_log_force (pag_mount (pag),XFS_LOG_SYNC );trace_xfs_extent_busy_force (pag, fbno, flen);spin_lock (&pag->pagb_lock);return false;
@@ -659,7 +659,7 @@ xfs_extent_busy_ag_cmp( container_of(l2, struct xfs_extent_busy, list);s32 diff; - diff = b1->pag->pag_agno - b2->pag->pag_agno; + diff =pag_agno (b1->pag) -pag_agno (b2->pag);if (!diff) diff = b1->bno - b2->bno;return diff;
fs/xfs/xfs_extfree_item.c +1 -1
@@ -362,7 +362,7 @@ xfs_extent_free_diff_items(struct xfs_extent_free_item *ra =xefi_entry (a);struct xfs_extent_free_item *rb =xefi_entry (b); -return ra->xefi_pag->pag_agno - rb->xefi_pag->pag_agno; +return pag_agno (ra->xefi_pag) -pag_agno (rb->xefi_pag); }/* Log a free extent to the intent item. */
fs/xfs/xfs_filestream.c +4 -4
@@ -90,7 +90,7 @@ xfs_filestream_pick_ag( maxfree = pag->pagf_freeblks;if (max_pag)xfs_perag_rele (max_pag); -atomic_inc (&pag->pag_active_ref); +atomic_inc (&pag_group (pag)->xg_active_ref); max_pag = pag; }
@@ -225,7 +225,7 @@ xfs_filestream_lookup_association(* down immediately after we mark the lookup as done. */ pag = container_of(mru, struct xfs_fstrm_item, mru)->pag; -atomic_inc (&pag->pag_active_ref); +atomic_inc (&pag_group (pag)->xg_active_ref);xfs_mru_cache_done (mp->m_filestream);trace_xfs_filestream_lookup (pag, ap->ip->i_ino);
@@ -278,7 +278,7 @@ xfs_filestream_create_association(struct xfs_fstrm_item *item = container_of(mru, struct xfs_fstrm_item, mru); - agno = (item->pag->pag_agno +1 ) % mp->m_sb.sb_agcount; + agno = (pag_agno (item->pag) +1 ) % mp->m_sb.sb_agcount;xfs_fstrm_free_func (mp, mru); }else if (xfs_is_inode32 (mp)) {xfs_agnumber_t rotorstep = xfs_rotorstep;
@@ -317,7 +317,7 @@ xfs_filestream_create_association(if (!item) goto out_put_fstrms; -atomic_inc (&args->pag->pag_active_ref); +atomic_inc (&pag_group (args->pag)->xg_active_ref); item->pag = args->pag; error =xfs_mru_cache_insert (mp->m_filestream, pino, &item->mru);if (error)
fs/xfs/xfs_fsmap.c +6 -6
@@ -353,7 +353,7 @@ xfs_getfsmap_helper(return -ECANCELED ;trace_xfs_fsmap_mapping (mp, info->dev, - info->pag ? info->pag->pag_agno :NULLAGNUMBER , rec); + info->pag ?pag_agno (info->pag) :NULLAGNUMBER , rec); fmr.fmr_device = info->dev; fmr.fmr_physical = rec_daddr;
@@ -519,7 +519,7 @@ __xfs_getfsmap_datadev(* is the last AG that we're querying. */ info->pag = pag; -if (pag->pag_agno == end_ag) { +if (pag_agno (pag) == end_ag) { info->high.rm_startblock =XFS_FSB_TO_AGBNO (mp, end_fsb); info->high.rm_offset = XFS_BB_TO_FSBT(mp,
@@ -541,9 +541,9 @@ __xfs_getfsmap_datadev(if (error)break ; -trace_xfs_fsmap_low_key (mp, info->dev, pag->pag_agno, +trace_xfs_fsmap_low_key (mp, info->dev,pag_agno (pag), &info->low); -trace_xfs_fsmap_high_key (mp, info->dev, pag->pag_agno, +trace_xfs_fsmap_high_key (mp, info->dev,pag_agno (pag), &info->high); error =query_fn (tp, info, &bt_cur, priv);
@@ -554,7 +554,7 @@ __xfs_getfsmap_datadev(* Set the AG low key to the start of the AG prior to * moving on to the next AG. */ -if (pag->pag_agno == start_ag) +if (pag_agno (pag) == start_ag)memset (&info->low,0 ,sizeof (info->low));/*
@@ -562,7 +562,7 @@ __xfs_getfsmap_datadev(* before we drop the reference to the perag when the loop * terminates. */ -if (pag->pag_agno == end_ag) { +if (pag_agno (pag) == end_ag) { info->last = true; error =query_fn (tp, info, &bt_cur, priv);if (error)
fs/xfs/xfs_icache.c +18 -37
149 lines not on this page · raw message
fs/xfs/xfs_inode.c +3 -3
@@ -1514,7 +1514,7 @@ xfs_iunlink_reload_next( xfs_agino_t next_agino) {struct xfs_perag *pag = agibp->b_pag; -struct xfs_mount *mp = pag->pag_mount; +struct xfs_mount *mp =pag_mount (pag);struct xfs_inode *next_ip =NULL ;int error;
@@ -1529,7 +1529,7 @@ xfs_iunlink_reload_next(xfs_info_ratelimited (mp,"Found unrecovered unlinked inode 0x%x in AG 0x%x. Initiating recovery." , - next_agino, pag->pag_agno); + next_agino,pag_agno (pag));/* * Use an untrusted lookup just to be cautious in case the AGI has been
@@ -1572,7 +1572,7 @@ xfs_ifree_mark_inode_stale( struct xfs_inode *free_ip, xfs_ino_t inum) { -struct xfs_mount *mp = pag->pag_mount; +struct xfs_mount *mp =pag_mount (pag);struct xfs_inode_log_item *iip;struct xfs_inode *ip;
fs/xfs/xfs_iwalk.c +3 -3
@@ -188,7 +188,7 @@ xfs_iwalk_ag_recs(return 0 ;if (iwag->inobt_walk_fn) { - error = iwag->inobt_walk_fn (mp, tp, pag->pag_agno, irec, + error = iwag->inobt_walk_fn (mp, tp,pag_agno (pag), irec, iwag->data);if (error)return error;
@@ -405,7 +405,7 @@ xfs_iwalk_ag(int error =0 ;/* Set up our cursor at the right place in the inode btree. */ -ASSERT (pag->pag_agno ==XFS_INO_TO_AGNO (mp, iwag->startino)); +ASSERT (pag_agno (pag) ==XFS_INO_TO_AGNO (mp, iwag->startino)); agino =XFS_INO_TO_AGINO (mp, iwag->startino); error =xfs_iwalk_ag_start (iwag, agino, &cur, &agi_bp, &has_more);
@@ -677,7 +677,7 @@ xfs_iwalk_threaded( iwag->sz_recs =xfs_iwalk_prefetch (inode_records); iwag->lastino =NULLFSINO ;xfs_pwork_queue (&pctl, &iwag->pwork); - startino =XFS_AGINO_TO_INO (mp, pag->pag_agno +1 ,0 ); + startino =XFS_AGINO_TO_INO (mp,pag_agno (pag) +1 ,0 );if (flags &XFS_IWALK_SAME_AG )break ; }
fs/xfs/xfs_log_recover.c +3 -3
@@ -2677,7 +2677,7 @@ xlog_recover_clear_agi_bucket( struct xfs_perag *pag, int bucket) { -struct xfs_mount *mp = pag->pag_mount; +struct xfs_mount *mp =pag_mount (pag);struct xfs_trans *tp;struct xfs_agi *agi;struct xfs_buf *agibp;
@@ -2708,7 +2708,7 @@ xlog_recover_clear_agi_bucket(xfs_trans_cancel (tp); out_error:xfs_warn (mp,"%s: failed to clear agi %d. Continuing." , __func__, - pag->pag_agno); +pag_agno (pag));return ; }
@@ -2718,7 +2718,7 @@ xlog_recover_iunlink_bucket( struct xfs_agi *agi, int bucket) { -struct xfs_mount *mp = pag->pag_mount; +struct xfs_mount *mp =pag_mount (pag);struct xfs_inode *prev_ip =NULL ;struct xfs_inode *ip;xfs_agino_t prev_agino, agino;
fs/xfs/xfs_mount.h +5 -1
@@ -71,6 +71,10 @@ struct xfs_inodegc {unsigned int cpu; }; +struct xfs_groups { +struct xarray xa; +}; +/* * The struct xfsmount layout is optimised to separate read-mostly variables * from variables that are frequently modified. We put the read-mostly variables
@@ -208,7 +212,7 @@ typedef struct xfs_mount {*/ atomic64_t m_allocbt_blks; -struct xarray m_perags;/* per-ag accounting info */ +struct xfs_groups m_groups[XG_TYPE_MAX ];uint64_t m_resblks;/* total reserved blocks */ uint64_t m_resblks_avail;/* available reserved blocks */ uint64_t m_resblks_save;/* reserved blks @ remount,ro */
fs/xfs/xfs_refcount_item.c +1 -1
@@ -244,7 +244,7 @@ xfs_refcount_update_diff_items(struct xfs_refcount_intent *ra =ci_entry (a);struct xfs_refcount_intent *rb =ci_entry (b); -return ra->ri_pag->pag_agno - rb->ri_pag->pag_agno; +return pag_agno (ra->ri_pag) -pag_agno (rb->ri_pag); }/* Log refcount updates in the intent item. */
fs/xfs/xfs_reflink.c +1 -1
@@ -144,7 +144,7 @@ xfs_reflink_find_shared(if (error)return error; - cur =xfs_refcountbt_init_cursor (pag->pag_mount, tp, agbp, pag); + cur =xfs_refcountbt_init_cursor (pag_mount (pag), tp, agbp, pag); error =xfs_refcount_find_shared (cur, agbno, aglen, fbno, flen, find_end_of_shared);
fs/xfs/xfs_rmap_item.c +1 -1
@@ -243,7 +243,7 @@ xfs_rmap_update_diff_items(struct xfs_rmap_intent *ra =ri_entry (a);struct xfs_rmap_intent *rb =ri_entry (b); -return ra->ri_pag->pag_agno - rb->ri_pag->pag_agno; +return pag_agno (ra->ri_pag) -pag_agno (rb->ri_pag); }/* Log rmap updates in the intent item. */
fs/xfs/xfs_super.c +7 -4
@@ -238,7 +238,7 @@ xfs_set_inode_alloc_perag( xfs_ino_t ino, xfs_agnumber_t max_metadata) { -if (!xfs_is_inode32 (pag->pag_mount)) { +if (!xfs_is_inode32 (pag_mount (pag))) {set_bit (XFS_AGSTATE_ALLOWS_INODES , &pag->pag_opstate);clear_bit (XFS_AGSTATE_PREFERS_METADATA , &pag->pag_opstate);return false;
@@ -251,7 +251,7 @@ xfs_set_inode_alloc_perag( }set_bit (XFS_AGSTATE_ALLOWS_INODES , &pag->pag_opstate); -if (pag->pag_agno < max_metadata) +if (pag_agno (pag) < max_metadata)set_bit (XFS_AGSTATE_PREFERS_METADATA , &pag->pag_opstate);else clear_bit (XFS_AGSTATE_PREFERS_METADATA , &pag->pag_opstate);
@@ -2011,17 +2011,20 @@ static const struct fs_context_operations xfs_context_ops = {* mount option parsing having already been performed as this can be called from * fsopen() before any parameters have been set. */ -static int xfs_init_fs_context ( +static int +xfs_init_fs_context (struct fs_context *fc) {struct xfs_mount *mp; +int i; mp =kzalloc (sizeof (struct xfs_mount ),GFP_KERNEL | __GFP_NOFAIL);if (!mp)return -ENOMEM ;spin_lock_init (&mp->m_sb_lock); -xa_init (&mp->m_perags); +for (i =0 ; i <XG_TYPE_MAX ; i++) +xa_init (&mp->m_groups[i].xa);mutex_init (&mp->m_growlock);INIT_WORK (&mp->m_flush_inodes_work, xfs_flush_inodes_worker);INIT_DELAYED_WORK (&mp->m_reclaim_work, xfs_reclaim_worker);
fs/xfs/xfs_trace.c +1 -0
@@ -11,6 +11,7 @@#include "xfs_log_format.h" #include "xfs_trans_resv.h" #include "xfs_mount.h" +#include "xfs_group.h" #include "xfs_defer.h" #include "xfs_da_format.h" #include "xfs_inode.h"
fs/xfs/xfs_trace.h +93 -56
354 lines not on this page · raw message
PATCH 3/16 xfs: add a xfs_group_next_range helper
In reply to Darrick J. WongFrom: Christoph Hellwig <[email protected]>
Add a helper to iterate over iterate over all groups, which can be used as a simple while loop:
struct xfs_group *xg = NULL;
while ((xg = xfs_group_next_range(mp, xg, 0, MAX_GROUP))) {
...
}This will be wrapped by the realtime group code first, and eventually replace the for_each_rtgroup_from and for_each_rtgroup_range helpers.
--- fs/xfs/libxfs/xfs_group.c | 26 ++++++++++++++++++++++++++ fs/xfs/libxfs/xfs_group.h | 3 +++ 2 files changed, 29 insertions(+)
fs/xfs/libxfs/xfs_group.c +26 -0
@@ -87,6 +87,32 @@ xfs_group_grab(return xg; } +/* +* Iterate to the next group. To start the iteration at @start_index, a %NULL +* @xg is passed, else the previous group returned from this function. The +* caller should break out of the loop when this returns %NULL. If the caller +* wants to break out of a loop that did not finish it needs to release the +* active reference to @xg using xfs_group_rele() itself. +*/ +struct xfs_group * +xfs_group_next_range ( +struct xfs_mount *mp, +struct xfs_group *xg, +uint32_t start_index, +uint32_t end_index, +enum xfs_group_type type) +{ +uint32_t index = start_index; + +if (xg) { + index = xg->xg_gno +1 ; +xfs_group_rele (xg); + } +if (index > end_index) +return NULL ; +return xfs_group_grab (mp, index, type); +} +/* * Find the next group after @xg, or the first group if @xg is NULL. */
fs/xfs/libxfs/xfs_group.h +3 -0
@@ -20,6 +20,9 @@ void xfs_group_put(struct xfs_group *xg);struct xfs_group *xfs_group_grab (struct xfs_mount *mp,uint32_t index,enum xfs_group_type type); +struct xfs_group *xfs_group_next_range (struct xfs_mount *mp, +struct xfs_group *xg,uint32_t start_index,uint32_t end_index, +enum xfs_group_type type);struct xfs_group *xfs_group_grab_next_mark (struct xfs_mount *mp,struct xfs_group *xg,xa_mark_t mark,enum xfs_group_type type);void xfs_group_rele (struct xfs_group *xg);
PATCH 4/16 xfs: switch perag iteration from the for_each macros to a while based iterator
In reply to Darrick J. WongFrom: Christoph Hellwig <[email protected]>
The current for_each_perag* macros are a bit annoying in that they require the caller to both provide an object and an index iterator, and also somewhat obsfucate the underlying control flow mechanism.
Switch to open coded while loops using new xfs_perag_next{,_from,_range} helpers that return the next pag structure to iterate on based on the previous one or NULL for the loop start.
--- fs/xfs/libxfs/xfs_ag.h | 62 +++++++++++++++++++------------------------ fs/xfs/libxfs/xfs_sb.c | 15 +++------- fs/xfs/libxfs/xfs_types.c | 5 +-- fs/xfs/scrub/bmap.c | 5 +-- fs/xfs/scrub/bmap_repair.c | 5 +-- fs/xfs/scrub/fscounters.c | 10 +++---- fs/xfs/scrub/health.c | 11 +++----- fs/xfs/scrub/inode_repair.c | 5 +-- fs/xfs/xfs_discard.c | 6 ++-- fs/xfs/xfs_extent_busy.c | 5 +-- fs/xfs/xfs_fsmap.c | 7 ++--- fs/xfs/xfs_fsops.c | 10 +++---- fs/xfs/xfs_health.c | 5 +-- fs/xfs/xfs_icache.c | 5 +-- fs/xfs/xfs_iwalk.c | 18 +++++++----- fs/xfs/xfs_log_recover.c | 5 +-- fs/xfs/xfs_reflink.c | 5 +-- 17 files changed, 79 insertions(+), 105 deletions(-)
fs/xfs/libxfs/xfs_ag.h +28 -34
@@ -208,6 +208,34 @@ xfs_perag_rele(xfs_group_rele (pag_group (pag)); } +static inline struct xfs_perag * +xfs_perag_next_range ( +struct xfs_mount *mp, +struct xfs_perag *pag, +xfs_agnumber_t start_agno, +xfs_agnumber_t end_agno) +{ +return to_perag (xfs_group_next_range (mp, pag ?pag_group (pag) :NULL , + start_agno, end_agno,XG_TYPE_AG )); +} + +static inline struct xfs_perag * +xfs_perag_next_from ( +struct xfs_mount *mp, +struct xfs_perag *pag, +xfs_agnumber_t start_agno) +{ +return xfs_perag_next_range (mp, pag, start_agno, mp->m_sb.sb_agcount -1 ); +} + +static inline struct xfs_perag * +xfs_perag_next ( +struct xfs_mount *mp, +struct xfs_perag *pag) +{ +return xfs_perag_next_from (mp, pag,0 ); +} +/* * Per-ag geometry infomation and validation */
@@ -273,40 +301,6 @@ xfs_ag_contains_log(struct xfs_mount *mp, xfs_agnumber_t agno) agno ==XFS_FSB_TO_AGNO (mp, mp->m_sb.sb_logstart); } -/* -* Perag iteration APIs -*/ -static inline struct xfs_perag * -xfs_perag_next ( -struct xfs_perag *pag, -xfs_agnumber_t *agno, -xfs_agnumber_t end_agno) -{ -struct xfs_mount *mp =pag_mount (pag); - - *agno =pag_agno (pag) +1 ; -xfs_perag_rele (pag); -while (*agno <= end_agno) { - pag =xfs_perag_grab (mp, *agno); -if (pag) -return pag; - (*agno)++; - } -return NULL ; -} - -#define for_each_perag_range (mp, agno, end_agno, pag) \ - for ((pag) = xfs_perag_grab((mp), (agno)); \ - (pag) != NULL; \ - (pag) = xfs_perag_next((pag), &(agno), (end_agno))) - -#define for_each_perag_from (mp, agno, pag) \ - for_each_perag_range((mp), (agno), (mp)->m_sb.sb_agcount - 1, (pag)) - -#define for_each_perag (mp, agno, pag) \ - (agno) = 0; \ - for_each_perag_from((mp), (agno), (pag)) -static inline struct xfs_perag * xfs_perag_next_wrap( struct xfs_perag *pag,
fs/xfs/libxfs/xfs_sb.c +5 -10
@@ -1109,14 +1109,13 @@ intxfs_update_secondary_sbs ( struct xfs_mount *mp) { -struct xfs_perag *pag; -xfs_agnumber_t agno =1 ; +struct xfs_perag *pag =NULL ;int saved_error =0 ;int error =0 ;LIST_HEAD (buffer_list);/* update secondary superblocks. */ -for_each_perag_from (mp, agno, pag) { +while ((pag =xfs_perag_next_from (mp, pag,1 ))) {struct xfs_buf *bp; error = xfs_buf_get(mp->m_ddev_targp,
@@ -1146,7 +1145,7 @@ xfs_update_secondary_sbs(xfs_buf_relse (bp);/* don't hold too many buffers at once */ -if (agno %16 ) +if (pag_agno (pag) %16 )continue ; error =xfs_buf_delwri_submit (&buffer_list);
@@ -1160,12 +1159,8 @@ xfs_update_secondary_sbs( } } error =xfs_buf_delwri_submit (&buffer_list); -if (error) { -xfs_warn (mp, -"write error %d updating a secondary superblock near ag %d" , - error, agno); - } - +if (error) +xfs_warn (mp,"error %d writing secondary superblocks" , error);return saved_error ? saved_error : error; }
fs/xfs/libxfs/xfs_types.c +2 -3
@@ -170,13 +170,12 @@ xfs_icount_range( unsigned long long *max) {unsigned long long nr_inos =0 ; -struct xfs_perag *pag; -xfs_agnumber_t agno; +struct xfs_perag *pag =NULL ;/* root, rtbitmap, rtsum all live in the first chunk */ *min =XFS_INODES_PER_CHUNK ; -for_each_perag (mp, agno, pag) +while ((pag =xfs_perag_next (mp, pag))) nr_inos += pag->agino_max - pag->agino_min +1 ; *max = nr_inos; }
fs/xfs/scrub/bmap.c +2 -3
@@ -760,11 +760,10 @@ xchk_bmap_check_rmaps( struct xfs_scrub *sc, int whichfork) { -struct xfs_perag *pag; -xfs_agnumber_t agno; +struct xfs_perag *pag =NULL ;int error; -for_each_perag (sc->mp, agno, pag) { +while ((pag =xfs_perag_next (sc->mp, pag))) { error =xchk_bmap_check_ag_rmaps (sc, whichfork, pag);if (error || (sc->sm->sm_flags &XFS_SCRUB_OFLAG_CORRUPT )) {
fs/xfs/scrub/bmap_repair.c +2 -3
@@ -407,12 +407,11 @@ xrep_bmap_find_mappings( struct xrep_bmap *rb) {struct xfs_scrub *sc = rb->sc; -struct xfs_perag *pag; -xfs_agnumber_t agno; +struct xfs_perag *pag =NULL ;int error =0 ;/* Iterate the rmaps for extents. */ -for_each_perag (sc->mp, agno, pag) { +while ((pag =xfs_perag_next (sc->mp, pag))) { error =xrep_bmap_scan_ag (rb, pag);if (error) {xfs_perag_rele (pag);
fs/xfs/scrub/fscounters.c +4 -6
@@ -74,10 +74,9 @@ xchk_fscount_warmup(struct xfs_buf *agi_bp =NULL ;struct xfs_buf *agf_bp =NULL ;struct xfs_perag *pag =NULL ; -xfs_agnumber_t agno;int error =0 ; -for_each_perag (mp, agno, pag) { +while ((pag =xfs_perag_next (mp, pag))) {if (xchk_should_terminate (sc, &error))break ; if (xfs_perag_initialised_agi(pag) &&
@@ -295,9 +294,8 @@ xchk_fscount_aggregate_agcounts( struct xchk_fscounters *fsc) {struct xfs_mount *mp = sc->mp; -struct xfs_perag *pag; +struct xfs_perag *pag =NULL ;uint64_t delayed; -xfs_agnumber_t agno;int tries =8 ;int error =0 ;
@@ -306,7 +304,7 @@ xchk_fscount_aggregate_agcounts( fsc->ifree =0 ; fsc->fdblocks =0 ; -for_each_perag (mp, agno, pag) { +while ((pag =xfs_perag_next (mp, pag))) {if (xchk_should_terminate (sc, &error))break ;
@@ -327,7 +325,7 @@ xchk_fscount_aggregate_agcounts(if (xfs_has_lazysbcount (sc->mp)) { fsc->fdblocks += pag->pagf_btreeblks; }else { - error =xchk_fscount_btreeblks (sc, fsc, agno); + error =xchk_fscount_btreeblks (sc, fsc,pag_agno (pag));if (error)break ; }
fs/xfs/scrub/health.c +4 -7
@@ -160,12 +160,11 @@ STATIC voidxchk_mark_all_healthy ( struct xfs_mount *mp) { -struct xfs_perag *pag; -xfs_agnumber_t agno; +struct xfs_perag *pag =NULL ;xfs_fs_mark_healthy (mp,XFS_SICK_FS_INDIRECT );xfs_rt_mark_healthy (mp,XFS_SICK_RT_INDIRECT ); -for_each_perag (mp, agno, pag) +while ((pag =xfs_perag_next (mp, pag)))xfs_ag_mark_healthy (pag,XFS_SICK_AG_INDIRECT ); }
@@ -294,9 +293,7 @@ xchk_health_record( struct xfs_scrub *sc) {struct xfs_mount *mp = sc->mp; -struct xfs_perag *pag; -xfs_agnumber_t agno; - +struct xfs_perag *pag =NULL ;unsigned int sick;unsigned int checked;
@@ -308,7 +305,7 @@ xchk_health_record(if (sick &XFS_SICK_RT_PRIMARY )xchk_set_corrupt (sc); -for_each_perag (mp, agno, pag) { +while ((pag =xfs_perag_next (mp, pag))) {xfs_ag_measure_sickness (pag, &sick, &checked);if (sick &XFS_SICK_AG_PRIMARY )xchk_set_corrupt (sc);
fs/xfs/scrub/inode_repair.c +2 -3
@@ -761,14 +761,13 @@ STATIC intxrep_dinode_count_rmaps ( struct xrep_inode *ri) { -struct xfs_perag *pag; -xfs_agnumber_t agno; +struct xfs_perag *pag =NULL ;int error;if (!xfs_has_rmapbt (ri->sc->mp) ||xfs_has_realtime (ri->sc->mp))return -EOPNOTSUPP ; -for_each_perag (ri->sc->mp, agno, pag) { +while ((pag =xfs_perag_next (ri->sc->mp, pag))) { error =xrep_dinode_count_ag_rmaps (ri, pag);if (error) {xfs_perag_rele (pag);
fs/xfs/xfs_discard.c +3 -3
@@ -387,8 +387,8 @@ xfs_trim_datadev_extents( {xfs_agnumber_t start_agno, end_agno;xfs_agblock_t start_agbno, end_agbno; +struct xfs_perag *pag =NULL ;xfs_daddr_t ddev_end; -struct xfs_perag *pag;int last_error =0 , error; ddev_end = min_t(xfs_daddr_t, end,
@@ -399,10 +399,10 @@ xfs_trim_datadev_extents( end_agno =xfs_daddr_to_agno (mp, ddev_end); end_agbno =xfs_daddr_to_agbno (mp, ddev_end); -for_each_perag_range (mp, start_agno, end_agno, pag) { +while ((pag =xfs_perag_next_range (mp, pag, start_agno, end_agno))) {xfs_agblock_t agend = pag->block_count; -if (start_agno == end_agno) +if (pag_agno (pag) == end_agno) agend = end_agbno; error =xfs_trim_perag_extents (pag, start_agbno, agend, minlen);if (error)
fs/xfs/xfs_extent_busy.c +2 -3
@@ -629,11 +629,10 @@ voidxfs_extent_busy_wait_all ( struct xfs_mount *mp) { -struct xfs_perag *pag; +struct xfs_perag *pag =NULL ;DEFINE_WAIT (wait); -xfs_agnumber_t agno; -for_each_perag (mp, agno, pag) { +while ((pag =xfs_perag_next (mp, pag))) { do { prepare_to_wait(&pag->pagb_wait, &wait, TASK_KILLABLE); if (RB_EMPTY_ROOT(&pag->pagb_tree))
fs/xfs/xfs_fsmap.c +3 -4
@@ -460,11 +460,11 @@ __xfs_getfsmap_datadev( void *priv) {struct xfs_mount *mp = tp->t_mountp; -struct xfs_perag *pag; +struct xfs_perag *pag =NULL ;struct xfs_btree_cur *bt_cur =NULL ;xfs_fsblock_t start_fsb;xfs_fsblock_t end_fsb; -xfs_agnumber_t start_ag, end_ag, ag; +xfs_agnumber_t start_ag, end_ag;uint64_t eofs;int error =0 ;
@@ -512,8 +512,7 @@ __xfs_getfsmap_datadev( start_ag =XFS_FSB_TO_AGNO (mp, start_fsb); end_ag =XFS_FSB_TO_AGNO (mp, end_fsb); - ag = start_ag; -for_each_perag_range (mp, ag, end_ag, pag) { +while ((pag =xfs_perag_next_range (mp, pag, start_ag, end_ag))) {/* * Set the AG high key from the fsmap high key if this * is the last AG that we're querying.
fs/xfs/xfs_fsops.c +4 -6
@@ -528,13 +528,12 @@ intxfs_fs_reserve_ag_blocks ( struct xfs_mount *mp) { -xfs_agnumber_t agno; -struct xfs_perag *pag; +struct xfs_perag *pag =NULL ;int error =0 ;int err2; mp->m_finobt_nores = false; -for_each_perag (mp, agno, pag) { +while ((pag =xfs_perag_next (mp, pag))) { err2 =xfs_ag_resv_init (pag,NULL );if (err2 && !error) error = err2;
@@ -556,9 +555,8 @@ voidxfs_fs_unreserve_ag_blocks ( struct xfs_mount *mp) { -xfs_agnumber_t agno; -struct xfs_perag *pag; +struct xfs_perag *pag =NULL ; -for_each_perag (mp, agno, pag) +while ((pag =xfs_perag_next (mp, pag)))xfs_ag_resv_free (pag); }
fs/xfs/xfs_health.c +2 -3
@@ -28,8 +28,7 @@ voidxfs_health_unmount ( struct xfs_mount *mp) { -struct xfs_perag *pag; -xfs_agnumber_t agno; +struct xfs_perag *pag =NULL ;unsigned int sick =0 ;unsigned int checked =0 ;bool warn = false;
@@ -38,7 +37,7 @@ xfs_health_unmount(return ;/* Measure AG corruption levels. */ -for_each_perag (mp, agno, pag) { +while ((pag =xfs_perag_next (mp, pag))) {xfs_ag_measure_sickness (pag, &sick, &checked);if (sick) {trace_xfs_ag_unfixed_corruption (pag, sick);
fs/xfs/xfs_icache.c +2 -3
@@ -1383,13 +1383,12 @@ voidxfs_blockgc_stop ( struct xfs_mount *mp) { -struct xfs_perag *pag; -xfs_agnumber_t agno; +struct xfs_perag *pag =NULL ;if (!xfs_clear_blockgc_enabled (mp))return ; -for_each_perag (mp, agno, pag) +while ((pag =xfs_perag_next (mp, pag)))cancel_delayed_work_sync (&pag->pag_blockgc_work);trace_xfs_blockgc_stop (mp, __return_address); }
fs/xfs/xfs_iwalk.c +10 -8
@@ -540,23 +540,25 @@ xfs_iwalk_args( unsigned int flags) {struct xfs_mount *mp = iwag->mp; -xfs_agnumber_t agno =XFS_INO_TO_AGNO (mp, iwag->startino); +xfs_agnumber_t start_agno;int error; -ASSERT (agno < mp->m_sb.sb_agcount); + start_agno =XFS_INO_TO_AGNO (iwag->mp, iwag->startino); +ASSERT (start_agno < iwag->mp->m_sb.sb_agcount);ASSERT (!(flags & ~XFS_IWALK_FLAGS_ALL )); error =xfs_iwalk_alloc (iwag);if (error)return error; -for_each_perag_from (mp, agno, iwag->pag) { +while ((iwag->pag =xfs_perag_next_from (mp, iwag->pag, start_agno))) { error =xfs_iwalk_ag (iwag);if (error || (flags &XFS_IWALK_SAME_AG )) {xfs_perag_rele (iwag->pag);break ; } - iwag->startino =XFS_AGINO_TO_INO (mp, agno +1 ,0 ); + iwag->startino = +XFS_AGINO_TO_INO (mp,pag_agno (iwag->pag) +1 ,0 ); }xfs_iwalk_free (iwag);
@@ -644,19 +646,19 @@ xfs_iwalk_threaded(bool polled, void *data) { + xfs_agnumber_t start_agno = XFS_INO_TO_AGNO(mp, startino);struct xfs_pwork_ctl pctl; -struct xfs_perag *pag; -xfs_agnumber_t agno =XFS_INO_TO_AGNO (mp, startino); +struct xfs_perag *pag =NULL ;int error; -ASSERT (agno < mp->m_sb.sb_agcount); +ASSERT (start_agno < mp->m_sb.sb_agcount);ASSERT (!(flags & ~XFS_IWALK_FLAGS_ALL )); error =xfs_pwork_init (mp, &pctl, xfs_iwalk_ag_work,"xfs_iwalk" );if (error)return error; -for_each_perag_from (mp, agno, pag) { +while ((pag =xfs_perag_next_from (mp, pag, start_agno))) {struct xfs_iwalk_ag *iwag;if (xfs_pwork_ctl_want_abort (&pctl))
fs/xfs/xfs_log_recover.c +2 -3
@@ -2845,10 +2845,9 @@ static voidxlog_recover_process_iunlinks ( struct xlog *log) { -struct xfs_perag *pag; -xfs_agnumber_t agno; +struct xfs_perag *pag =NULL ; -for_each_perag (log->l_mp, agno, pag) +while ((pag =xfs_perag_next (log->l_mp, pag)))xlog_recover_iunlink_ag (pag); }
fs/xfs/xfs_reflink.c +2 -3
@@ -894,14 +894,13 @@ intxfs_reflink_recover_cow ( struct xfs_mount *mp) { -struct xfs_perag *pag; -xfs_agnumber_t agno; +struct xfs_perag *pag =NULL ;int error =0 ;if (!xfs_has_reflink (mp))return 0 ; -for_each_perag (mp, agno, pag) { +while ((pag =xfs_perag_next (mp, pag))) { error =xfs_refcount_recover_cow_leftovers (mp, pag);if (error) {xfs_perag_rele (pag);
PATCH 5/16 xfs: move metadata health tracking to the generic group structure
In reply to Darrick J. WongFrom: Christoph Hellwig <[email protected]>
Prepare for also tracking the health status of the upcoming realtime groups by moving the health tracking code to the generic xfs_group structure.
--- fs/xfs/libxfs/xfs_ag.c | 1 - fs/xfs/libxfs/xfs_ag.h | 9 ------ fs/xfs/libxfs/xfs_group.c | 4 ++ fs/xfs/libxfs/xfs_group.h | 12 +++++++ fs/xfs/libxfs/xfs_health.h | 45 +++++++++++----------------- fs/xfs/scrub/health.c | 8 ++--- fs/xfs/xfs_health.c | 71 ++++++++++++++++++++++++-------------------- fs/xfs/xfs_trace.h | 35 ++++++++++++---------- 8 files changed, 94 insertions(+), 91 deletions(-)
fs/xfs/libxfs/xfs_ag.c +0 -1
@@ -232,7 +232,6 @@ xfs_perag_alloc(/* Place kernel structure only init below this point. */ spin_lock_init (&pag->pag_ici_lock);spin_lock_init (&pag->pagb_lock); -spin_lock_init (&pag->pag_state_lock);INIT_DELAYED_WORK (&pag->pag_blockgc_work, xfs_blockgc_worker);INIT_RADIX_TREE (&pag->pag_ici_root,GFP_ATOMIC );xfs_defer_drain_init (&pag->pag_intents_drain);
fs/xfs/libxfs/xfs_ag.h +0 -9
@@ -69,13 +69,6 @@ struct xfs_perag {#ifdef __KERNEL__/* -- kernel only structures below this line -- */ -/* -* Bitsets of per-ag metadata that have been checked and/or are sick. -* Callers should hold pag_state_lock before accessing this field. -*/ -uint16_t pag_checked; -uint16_t pag_sick; -#ifdef CONFIG_XFS_ONLINE_REPAIR /* * Alternate btree heights so that online repair won't trip the write
@@ -87,8 +80,6 @@ struct xfs_perag {uint8_t pagf_repair_rmap_level;#endif -spinlock_t pag_state_lock; -spinlock_t pagb_lock;/* lock for pagb_tree */ struct rb_root pagb_tree;/* ordered tree of busy extents */ unsigned int pagb_gen;/* generation count for pagb_tree */
fs/xfs/libxfs/xfs_group.c +4 -0
@@ -182,6 +182,10 @@ xfs_group_insert( xg->xg_gno = index; xg->xg_type = type; +#ifdef __KERNEL__ +spin_lock_init (&xg->xg_state_lock); +#endif +/* Active ref owned by mount indicates group is online. */ atomic_set (&xg->xg_active_ref,1 );
fs/xfs/libxfs/xfs_group.h +12 -0
@@ -11,6 +11,18 @@ struct xfs_group {enum xfs_group_type xg_type;atomic_t xg_ref;/* passive reference count */ atomic_t xg_active_ref;/* active reference count */ + +#ifdef __KERNEL__ +/* -- kernel only structures below this line -- */ + +/* +* Bitsets of per-ag metadata that have been checked and/or are sick. +* Callers should hold xg_state_lock before accessing this field. +*/ +uint16_t xg_checked; +uint16_t xg_sick; +spinlock_t xg_state_lock; +#endif /* __KERNEL__ */ }; struct xfs_group *xfs_group_get(struct xfs_mount *mp, uint32_t index,
fs/xfs/libxfs/xfs_health.h +17 -28
73 lines not on this page · raw message
fs/xfs/scrub/health.c +4 -4
@@ -165,7 +165,7 @@ xchk_mark_all_healthy(xfs_fs_mark_healthy (mp,XFS_SICK_FS_INDIRECT );xfs_rt_mark_healthy (mp,XFS_SICK_RT_INDIRECT );while ((pag =xfs_perag_next (mp, pag))) -xfs_ag_mark_healthy (pag,XFS_SICK_AG_INDIRECT ); +xfs_group_mark_healthy (pag_group (pag),XFS_SICK_AG_INDIRECT ); }/*
@@ -206,9 +206,9 @@ xchk_update_health(case XHG_AG : pag =xfs_perag_get (sc->mp, sc->sm->sm_agno);if (bad) -xfs_ag_mark_corrupt (pag, sc->sick_mask); +xfs_group_mark_corrupt (pag_group (pag), sc->sick_mask);else -xfs_ag_mark_healthy (pag, sc->sick_mask); +xfs_group_mark_healthy (pag_group (pag), sc->sick_mask);xfs_perag_put (pag);break ;case XHG_INO :
@@ -306,7 +306,7 @@ xchk_health_record(xchk_set_corrupt (sc);while ((pag =xfs_perag_next (mp, pag))) { -xfs_ag_measure_sickness (pag, &sick, &checked); +xfs_group_measure_sickness (pag_group (pag), &sick, &checked);if (sick &XFS_SICK_AG_PRIMARY )xchk_set_corrupt (sc); }
fs/xfs/xfs_health.c +38 -33
115 lines not on this page · raw message
fs/xfs/xfs_trace.h +19 -16
@@ -4220,31 +4220,34 @@ DEFINE_FS_CORRUPT_EVENT(xfs_rt_mark_corrupt);DEFINE_FS_CORRUPT_EVENT (xfs_rt_mark_healthy);DEFINE_FS_CORRUPT_EVENT (xfs_rt_unfixed_corruption); -DECLARE_EVENT_CLASS (xfs_ag_corrupt_class, - TP_PROTO(const struct xfs_perag *pag, unsigned int flags), -TP_ARGS (pag, flags), +DECLARE_EVENT_CLASS (xfs_group_corrupt_class, + TP_PROTO(const struct xfs_group *xg, unsigned int flags), +TP_ARGS (xg, flags),TP_STRUCT__entry ( __field(dev_t, dev) - __field(xfs_agnumber_t, agno) + __field(enum xfs_group_type, type) + __field(uint32_t, index) __field(unsigned int, flags) ),TP_fast_assign ( - __entry->dev = pag_mount(pag)->m_super->s_dev; - __entry->agno = pag_agno(pag); + __entry->dev = xg->xg_mount->m_super->s_dev; + __entry->type = xg->xg_type; + __entry->index = xg->xg_gno; __entry->flags = flags; ), -TP_printk ("dev %d:%d agno 0x%x flags 0x%x" , +TP_printk ("dev %d:%d %sno 0x%x flags 0x%x" ,MAJOR (__entry->dev),MINOR (__entry->dev), - __entry->agno, __entry->flags) +__print_symbolic (__entry->type,XG_TYPE_STRINGS ), + __entry->index, __entry->flags) ); -#define DEFINE_AG_CORRUPT_EVENT (name) \ -DEFINE_EVENT(xfs_ag_corrupt_class, name, \ - TP_PROTO(const struct xfs_perag *pag, unsigned int flags), \ - TP_ARGS(pag, flags)) -DEFINE_AG_CORRUPT_EVENT (xfs_ag_mark_sick); -DEFINE_AG_CORRUPT_EVENT (xfs_ag_mark_corrupt); -DEFINE_AG_CORRUPT_EVENT (xfs_ag_mark_healthy); -DEFINE_AG_CORRUPT_EVENT (xfs_ag_unfixed_corruption); +#define DEFINE_GROUP_CORRUPT_EVENT (name) \ +DEFINE_EVENT(xfs_group_corrupt_class, name, \ + TP_PROTO(const struct xfs_group *xg, unsigned int flags), \ + TP_ARGS(xg, flags)) +DEFINE_GROUP_CORRUPT_EVENT (xfs_group_mark_sick); +DEFINE_GROUP_CORRUPT_EVENT (xfs_group_mark_corrupt); +DEFINE_GROUP_CORRUPT_EVENT (xfs_group_mark_healthy); +DEFINE_GROUP_CORRUPT_EVENT (xfs_group_unfixed_corruption); DECLARE_EVENT_CLASS(xfs_inode_corrupt_class, TP_PROTO(struct xfs_inode *ip, unsigned int flags),
PATCH 6/16 xfs: mark xfs_perag_intent_{hold,rele} static
In reply to Darrick J. WongFrom: Christoph Hellwig <[email protected]>
These two functions are only used inside of xfs_drain.c, so mark them static.
--- fs/xfs/xfs_drain.c | 42 +++++++++++++++++++++--------------------- fs/xfs/xfs_drain.h | 6 ------ 2 files changed, 21 insertions(+), 27 deletions(-)
fs/xfs/xfs_drain.c +21 -21
@@ -93,6 +93,27 @@ static inline int xfs_defer_drain_wait(struct xfs_defer_drain *dr)return wait_event_killable (dr->dr_waiters, !xfs_defer_drain_busy (dr)); } +/* +* Declare an intent to update AG metadata. Other threads that need exclusive +* access can decide to back off if they see declared intentions. +*/ +static void +xfs_perag_intent_hold ( +struct xfs_perag *pag) +{ +trace_xfs_perag_intent_hold (pag, __return_address); +xfs_defer_drain_grab (&pag->pag_intents_drain); +} + +/* Release our intent to update this AG's metadata. */ +static void +xfs_perag_intent_rele ( +struct xfs_perag *pag) +{ +trace_xfs_perag_intent_rele (pag, __return_address); +xfs_defer_drain_rele (&pag->pag_intents_drain); +} +/* * Get a passive reference to the AG that contains a fsbno and declare an intent * to update its metadata.
@@ -124,27 +145,6 @@ xfs_perag_intent_put(xfs_perag_put (pag); } -/* -* Declare an intent to update AG metadata. Other threads that need exclusive -* access can decide to back off if they see declared intentions. -*/ -void -xfs_perag_intent_hold ( -struct xfs_perag *pag) -{ -trace_xfs_perag_intent_hold (pag, __return_address); -xfs_defer_drain_grab (&pag->pag_intents_drain); -} - -/* Release our intent to update this AG's metadata. */ -void -xfs_perag_intent_rele ( -struct xfs_perag *pag) -{ -trace_xfs_perag_intent_rele (pag, __return_address); -xfs_defer_drain_rele (&pag->pag_intents_drain); -} -/* * Wait for the intent update count for this AG to hit zero. * Callers must not hold any AG header buffers.
fs/xfs/xfs_drain.h +0 -6
@@ -65,9 +65,6 @@ struct xfs_perag *xfs_perag_intent_get(struct xfs_mount *mp, xfs_fsblock_t fsbno);void xfs_perag_intent_put (struct xfs_perag *pag); -void xfs_perag_intent_hold (struct xfs_perag *pag); -void xfs_perag_intent_rele (struct xfs_perag *pag); -int xfs_perag_intent_drain (struct xfs_perag *pag);bool xfs_perag_intent_busy (struct xfs_perag *pag);#else
@@ -80,9 +77,6 @@ struct xfs_defer_drain { /* empty */ }; xfs_perag_get((mp), XFS_FSB_TO_AGNO(mp, fsbno))#define xfs_perag_intent_put (pag) xfs_perag_put(pag) -static inline void xfs_perag_intent_hold (struct xfs_perag *pag) { } -static inline void xfs_perag_intent_rele (struct xfs_perag *pag) { } -#endif /* CONFIG_XFS_DRAIN_INTENTS */ #endif /* XFS_DRAIN_H_ */
PATCH 7/16 xfs: move draining of deferred operations to the generic group structure
In reply to Darrick J. WongFrom: Christoph Hellwig <[email protected]>
Prepare supporting the upcoming realtime groups feature by moving the deferred operation draining to the generic xfs_group structure.
--- fs/xfs/libxfs/xfs_ag.c | 7 ++----- fs/xfs/libxfs/xfs_ag.h | 9 --------- fs/xfs/libxfs/xfs_group.c | 4 ++++ fs/xfs/libxfs/xfs_group.h | 9 +++++++++ fs/xfs/scrub/common.c | 4 ++-- fs/xfs/xfs_drain.c | 46 ++++++++++++++++++++++++--------------------- fs/xfs/xfs_drain.h | 6 ++++-- fs/xfs/xfs_trace.h | 36 ++++++++++++++++++++--------------- 8 files changed, 66 insertions(+), 55 deletions(-)
fs/xfs/libxfs/xfs_ag.c +2 -5
@@ -112,7 +112,6 @@ xfs_perag_uninit(#ifdef __KERNEL__struct xfs_perag *pag =to_perag (xg); -xfs_defer_drain_free (&pag->pag_intents_drain);cancel_delayed_work_sync (&pag->pag_blockgc_work);xfs_buf_cache_destroy (&pag->pag_bcache);#endif
@@ -234,7 +233,6 @@ xfs_perag_alloc(spin_lock_init (&pag->pagb_lock);INIT_DELAYED_WORK (&pag->pag_blockgc_work, xfs_blockgc_worker);INIT_RADIX_TREE (&pag->pag_ici_root,GFP_ATOMIC ); -xfs_defer_drain_init (&pag->pag_intents_drain);init_waitqueue_head (&pag->pagb_wait); pag->pagb_tree =RB_ROOT ;xfs_hooks_init (&pag->pag_rmap_update_hooks);
@@ -242,7 +240,7 @@ xfs_perag_alloc( error =xfs_buf_cache_init (&pag->pag_bcache);if (error) - goto out_defer_drain_free; + goto out_free_perag;/* * Pre-calculated geometry
@@ -260,8 +258,7 @@ xfs_perag_alloc( out_buf_cache_destroy:xfs_buf_cache_destroy (&pag->pag_bcache); -out_defer_drain_free: -xfs_defer_drain_free (&pag->pag_intents_drain); +out_free_perag:kfree (pag);return error; }
fs/xfs/libxfs/xfs_ag.h +0 -9
@@ -97,15 +97,6 @@ struct xfs_perag {/* background prealloc block trimming */ struct delayed_work pag_blockgc_work; -/* -* We use xfs_drain to track the number of deferred log intent items -* that have been queued (but not yet processed) so that waiters (e.g. -* scrub) will not lock resources when other threads are in the middle -* of processing a chain of intent items only to find momentary -* inconsistencies. -*/ -struct xfs_defer_drain pag_intents_drain; -/* Hook to feed rmapbt updates to an active online repair. */ struct xfs_hooks pag_rmap_update_hooks;#endif /* __KERNEL__ */
fs/xfs/libxfs/xfs_group.c +4 -0
@@ -160,6 +160,8 @@ xfs_group_free(XFS_IS_CORRUPT (mp,atomic_read (&xg->xg_ref) !=0 ); +xfs_defer_drain_free (&xg->xg_intents_drain); +if (uninit)uninit (xg);
@@ -185,6 +187,7 @@ xfs_group_insert(#ifdef __KERNEL__spin_lock_init (&xg->xg_state_lock);#endif +xfs_defer_drain_init (&xg->xg_intents_drain);/* Active ref owned by mount indicates group is online. */ atomic_set (&xg->xg_active_ref,1 );
@@ -192,6 +195,7 @@ xfs_group_insert( error =xa_insert (&mp->m_groups[type].xa, index, xg,GFP_KERNEL );if (error) {WARN_ON_ONCE (error == -EBUSY ); +xfs_defer_drain_free (&xg->xg_intents_drain);return error; }
fs/xfs/libxfs/xfs_group.h +9 -0
@@ -22,6 +22,15 @@ struct xfs_group {uint16_t xg_checked;uint16_t xg_sick;spinlock_t xg_state_lock; + +/* +* We use xfs_drain to track the number of deferred log intent items +* that have been queued (but not yet processed) so that waiters (e.g. +* scrub) will not lock resources when other threads are in the middle +* of processing a chain of intent items only to find momentary +* inconsistencies. +*/ +struct xfs_defer_drain xg_intents_drain;#endif /* __KERNEL__ */ };
fs/xfs/scrub/common.c +2 -2
@@ -513,7 +513,7 @@ xchk_perag_drain_and_lock(* Obviously, this should be slanted against scrub and in favor * of runtime threads. */ -if (!xfs_perag_intent_busy (sa->pag)) +if (!xfs_group_intent_busy (pag_group (sa->pag)))return 0 ;if (sa->agf_bp) {
@@ -528,7 +528,7 @@ xchk_perag_drain_and_lock(if (!(sc->flags &XCHK_FSGATES_DRAIN ))return -ECHRNG ; - error =xfs_perag_intent_drain (sa->pag); + error =xfs_group_intent_drain (pag_group (sa->pag));if (error == -ERESTARTSYS ) error = -EINTR ; }while (!error);
fs/xfs/xfs_drain.c +25 -21
80 lines not on this page · raw message
fs/xfs/xfs_drain.h +4 -2
@@ -6,6 +6,7 @@#ifndef XFS_DRAIN_H_ #define XFS_DRAIN_H_ +struct xfs_group ;struct xfs_perag ;#ifdef CONFIG_XFS_DRAIN_INTENTS
@@ -65,8 +66,9 @@ struct xfs_perag *xfs_perag_intent_get(struct xfs_mount *mp, xfs_fsblock_t fsbno);void xfs_perag_intent_put (struct xfs_perag *pag); -int xfs_perag_intent_drain (struct xfs_perag *pag); -bool xfs_perag_intent_busy (struct xfs_perag *pag); +int xfs_group_intent_drain (struct xfs_group *xg); +bool xfs_group_intent_busy (struct xfs_group *xg); +#else struct xfs_defer_drain {/* empty */ };
fs/xfs/xfs_trace.h +20 -16
@@ -4689,35 +4689,39 @@ TRACE_EVENT(xfs_force_shutdown, );#ifdef CONFIG_XFS_DRAIN_INTENTS -DECLARE_EVENT_CLASS (xfs_perag_intents_class, - TP_PROTO(const struct xfs_perag *pag, void *caller_ip), -TP_ARGS (pag, caller_ip), +DECLARE_EVENT_CLASS (xfs_group_intents_class, + TP_PROTO(const struct xfs_group *xg, void *caller_ip), +TP_ARGS (xg, caller_ip),TP_STRUCT__entry ( __field(dev_t, dev) - __field(xfs_agnumber_t, agno) + __field(enum xfs_group_type, type) + __field(uint32_t, index) __field(long, nr_intents) __field(void *, caller_ip) ),TP_fast_assign ( - __entry->dev = pag_mount(pag)->m_super->s_dev; - __entry->agno = pag_agno(pag); - __entry->nr_intents = atomic_read(&pag->pag_intents_drain.dr_count); + __entry->dev = xg->xg_mount->m_super->s_dev; + __entry->type = xg->xg_type; + __entry->index = xg->xg_gno; + __entry->nr_intents = + atomic_read(&xg->xg_intents_drain.dr_count); __entry->caller_ip = caller_ip; ), -TP_printk ("dev %d:%d agno 0x%x intents %ld caller %pS" , +TP_printk ("dev %d:%d %sno 0x%x intents %ld caller %pS" ,MAJOR (__entry->dev),MINOR (__entry->dev), - __entry->agno, +__print_symbolic (__entry->type,XG_TYPE_STRINGS ), + __entry->index, __entry->nr_intents, __entry->caller_ip) ); -#define DEFINE_PERAG_INTENTS_EVENT (name) \ -DEFINE_EVENT(xfs_perag_intents_class, name, \ - TP_PROTO(const struct xfs_perag *pag, void *caller_ip), \ - TP_ARGS(pag, caller_ip)) -DEFINE_PERAG_INTENTS_EVENT (xfs_perag_intent_hold); -DEFINE_PERAG_INTENTS_EVENT (xfs_perag_intent_rele); -DEFINE_PERAG_INTENTS_EVENT (xfs_perag_wait_intents); +#define DEFINE_GROUP_INTENTS_EVENT (name) \ +DEFINE_EVENT(xfs_group_intents_class, name, \ + TP_PROTO(const struct xfs_group *xg, void *caller_ip), \ + TP_ARGS(xg, caller_ip)) +DEFINE_GROUP_INTENTS_EVENT (xfs_group_intent_hold); +DEFINE_GROUP_INTENTS_EVENT (xfs_group_intent_rele); +DEFINE_GROUP_INTENTS_EVENT (xfs_group_wait_intents);#endif /* CONFIG_XFS_DRAIN_INTENTS */
PATCH 8/16 xfs: move the online repair rmap hooks to the generic group structure
In reply to Darrick J. WongFrom: Christoph Hellwig <[email protected]>
Prepare for the upcoming realtime groups feature by moving the online repair rmap hooks to based to the generic xfs_group structure.
--- fs/xfs/libxfs/xfs_ag.c | 1 - fs/xfs/libxfs/xfs_ag.h | 3 --- fs/xfs/libxfs/xfs_group.c | 1 + fs/xfs/libxfs/xfs_group.h | 5 +++++ fs/xfs/libxfs/xfs_rmap.c | 24 +++++++++++++----------- fs/xfs/libxfs/xfs_rmap.h | 4 ++-- fs/xfs/scrub/rmap_repair.c | 4 ++-- 7 files changed, 23 insertions(+), 19 deletions(-)
fs/xfs/libxfs/xfs_ag.c +0 -1
@@ -235,7 +235,6 @@ xfs_perag_alloc(INIT_RADIX_TREE (&pag->pag_ici_root,GFP_ATOMIC );init_waitqueue_head (&pag->pagb_wait); pag->pagb_tree =RB_ROOT ; -xfs_hooks_init (&pag->pag_rmap_update_hooks);#endif /* __KERNEL__ */ error =xfs_buf_cache_init (&pag->pag_bcache);
fs/xfs/libxfs/xfs_ag.h +0 -3
@@ -96,9 +96,6 @@ struct xfs_perag {/* background prealloc block trimming */ struct delayed_work pag_blockgc_work; - -/* Hook to feed rmapbt updates to an active online repair. */ -struct xfs_hooks pag_rmap_update_hooks;#endif /* __KERNEL__ */ };
fs/xfs/libxfs/xfs_group.c +1 -0
@@ -186,6 +186,7 @@ xfs_group_insert(#ifdef __KERNEL__spin_lock_init (&xg->xg_state_lock); +xfs_hooks_init (&xg->xg_rmap_update_hooks);#endif xfs_defer_drain_init (&xg->xg_intents_drain);
fs/xfs/libxfs/xfs_group.h +5 -0
@@ -31,6 +31,11 @@ struct xfs_group {* inconsistencies. */ struct xfs_defer_drain xg_intents_drain; + +/* +* Hook to feed rmapbt updates to an active online repair. +*/ +struct xfs_hooks xg_rmap_update_hooks;#endif /* __KERNEL__ */ };
fs/xfs/libxfs/xfs_rmap.c +13 -11
@@ -835,7 +835,7 @@ xfs_rmap_hook_enable(void) static inline void xfs_rmap_update_hook( struct xfs_trans *tp, - struct xfs_perag *pag, + struct xfs_group *xg, enum xfs_rmap_intent_type op, xfs_agblock_t startblock, xfs_extlen_t blockcount,
@@ -850,27 +850,27 @@ xfs_rmap_update_hook( .oinfo = *oinfo, /* struct copy */ }; -if (pag) -xfs_hooks_call (&pag->pag_rmap_update_hooks, op, &p); +if (xg) +xfs_hooks_call (&xg->xg_rmap_update_hooks, op, &p); } }/* Call the specified function during a reverse mapping update. */ int xfs_rmap_hook_add ( -struct xfs_perag *pag, +struct xfs_group *xg,struct xfs_rmap_hook *hook) { -return xfs_hooks_add (&pag->pag_rmap_update_hooks, &hook->rmap_hook); +return xfs_hooks_add (&xg->xg_rmap_update_hooks, &hook->rmap_hook); }/* Stop calling the specified function during a reverse mapping update. */ void xfs_rmap_hook_del ( -struct xfs_perag *pag, +struct xfs_group *xg,struct xfs_rmap_hook *hook) { -xfs_hooks_del (&pag->pag_rmap_update_hooks, &hook->rmap_hook); +xfs_hooks_del (&xg->xg_rmap_update_hooks, &hook->rmap_hook); }/* Configure rmap update hook functions. */
@@ -905,7 +905,8 @@ xfs_rmap_free(return 0 ; cur =xfs_rmapbt_init_cursor (mp, tp, agbp, pag); -xfs_rmap_update_hook (tp, pag,XFS_RMAP_UNMAP , bno, len, false, oinfo); +xfs_rmap_update_hook (tp,pag_group (pag),XFS_RMAP_UNMAP , bno, len, + false, oinfo); error =xfs_rmap_unmap (cur, bno, len, false, oinfo);xfs_btree_del_cursor (cur, error);
@@ -1149,7 +1150,8 @@ xfs_rmap_alloc(return 0 ; cur =xfs_rmapbt_init_cursor (mp, tp, agbp, pag); -xfs_rmap_update_hook (tp, pag,XFS_RMAP_MAP , bno, len, false, oinfo); +xfs_rmap_update_hook (tp,pag_group (pag),XFS_RMAP_MAP , bno, len, false, + oinfo); error =xfs_rmap_map (cur, bno, len, false, oinfo);xfs_btree_del_cursor (cur, error);
@@ -2620,8 +2622,8 @@ xfs_rmap_finish_one(if (error)return error; -xfs_rmap_update_hook (tp, ri->ri_pag, ri->ri_type, bno, - ri->ri_bmap.br_blockcount, unwritten, &oinfo); +xfs_rmap_update_hook (tp,pag_group (ri->ri_pag), ri->ri_type, bno, + ri->ri_bmap.br_blockcount, unwritten, &oinfo);return 0 ; }
fs/xfs/libxfs/xfs_rmap.h +2 -2
@@ -264,8 +264,8 @@ struct xfs_rmap_hook {void xfs_rmap_hook_disable (void );void xfs_rmap_hook_enable (void ); -int xfs_rmap_hook_add (struct xfs_perag *pag,struct xfs_rmap_hook *hook); -void xfs_rmap_hook_del (struct xfs_perag *pag,struct xfs_rmap_hook *hook); +int xfs_rmap_hook_add (struct xfs_group *xg,struct xfs_rmap_hook *hook); +void xfs_rmap_hook_del (struct xfs_group *xg,struct xfs_rmap_hook *hook);void xfs_rmap_hook_setup (struct xfs_rmap_hook *hook,notifier_fn_t mod_fn);#endif
fs/xfs/scrub/rmap_repair.c +2 -2
@@ -1611,7 +1611,7 @@ xrep_rmap_setup_scan(*/ ASSERT (sc->flags &XCHK_FSGATES_RMAP );xfs_rmap_hook_setup (&rr->rhook, xrep_rmapbt_live_update); - error =xfs_rmap_hook_add (sc->sa.pag, &rr->rhook); + error =xfs_rmap_hook_add (pag_group (sc->sa.pag), &rr->rhook);if (error) goto out_iscan;return 0 ;
@@ -1632,7 +1632,7 @@ xrep_rmap_teardown(struct xfs_scrub *sc = rr->sc;xchk_iscan_abort (&rr->iscan); -xfs_rmap_hook_del (sc->sa.pag, &rr->rhook); +xfs_rmap_hook_del (pag_group (sc->sa.pag), &rr->rhook);xchk_iscan_teardown (&rr->iscan);xfbtree_destroy (&rr->rmap_btree);mutex_destroy (&rr->lock);
PATCH 9/16 xfs: return the busy generation from xfs_extent_busy_list_empty
In reply to Darrick J. WongFrom: Christoph Hellwig <[email protected]>
This avoid having to poke into the internals of the busy tracking in xrep_setup_ag_allocbt.
--- fs/xfs/scrub/alloc_repair.c | 9 +++------ fs/xfs/xfs_extent_busy.c | 4 +++- fs/xfs/xfs_extent_busy.h | 2 +- 3 files changed, 7 insertions(+), 8 deletions(-)
fs/xfs/scrub/alloc_repair.c +3 -6
@@ -132,16 +132,12 @@ intxrep_setup_ag_allocbt ( struct xfs_scrub *sc) { -unsigned int busy_gen; -/* * Make sure the busy extent list is clear because we can't put extents * on there twice. */ - busy_gen =READ_ONCE (sc->sa.pag->pagb_gen); -if (xfs_extent_busy_list_empty (sc->sa.pag)) +if (xfs_extent_busy_list_empty (sc->sa.pag, &busy_gen))return 0 ; -return xfs_extent_busy_flush (sc->tp, sc->sa.pag, busy_gen,0 ); }
@@ -849,6 +845,7 @@ xrep_allocbt( {struct xrep_abt *ra;struct xfs_mount *mp = sc->mp; +unsigned int busy_gen;char *descr;int error;
@@ -869,7 +866,7 @@ xrep_allocbt(* on there twice. In theory we cleared this before we started, but * let's not risk the filesystem. */ -if (!xfs_extent_busy_list_empty (sc->sa.pag)) { +if (!xfs_extent_busy_list_empty (sc->sa.pag, &busy_gen)) { error = -EDEADLOCK ; goto out_ra; }
fs/xfs/xfs_extent_busy.c +3 -1
@@ -667,12 +667,14 @@ xfs_extent_busy_ag_cmp(/* Are there any busy extents in this AG? */ bool xfs_extent_busy_list_empty ( -struct xfs_perag *pag) +struct xfs_perag *pag, +unsigned *busy_gen) {bool res;spin_lock (&pag->pagb_lock); res =RB_EMPTY_ROOT (&pag->pagb_tree); + *busy_gen =READ_ONCE (pag->pagb_gen);spin_unlock (&pag->pagb_lock);return res; }
fs/xfs/xfs_extent_busy.h +1 -1
@@ -83,6 +83,6 @@ static inline void xfs_extent_busy_sort(struct list_head *list) list_sort(NULL, list, xfs_extent_busy_ag_cmp); } -bool xfs_extent_busy_list_empty (struct xfs_perag *pag); +bool xfs_extent_busy_list_empty (struct xfs_perag *pag,unsigned int *busy_gen);#endif /* __XFS_EXTENT_BUSY_H__ */
PATCH 10/16 xfs: convert extent busy tracepoints to the generic group structure
In reply to Darrick J. WongFrom: Christoph Hellwig <[email protected]>
Prepare for tracking busy RT extents by passing the generic group structure to the xfs_extent_busy_class tracepoints.
--- fs/xfs/xfs_extent_busy.c | 12 +++++++----- fs/xfs/xfs_trace.h | 34 +++++++++++++++++++++------------- 2 files changed, 28 insertions(+), 18 deletions(-)
fs/xfs/xfs_extent_busy.c +7 -5
@@ -41,7 +41,7 @@ xfs_extent_busy_insert_list( new->flags = flags;/* trace before insert to be able to see failed inserts */ -trace_xfs_extent_busy (pag, bno, len); +trace_xfs_extent_busy (pag_group (pag), bno, len);spin_lock (&pag->pagb_lock); rbp = &pag->pagb_tree.rb_node;
@@ -278,13 +278,13 @@ xfs_extent_busy_update_extent(ASSERT (0 ); } -trace_xfs_extent_busy_reuse (pag, fbno, flen); +trace_xfs_extent_busy_reuse (pag_group (pag), fbno, flen);return true; out_force_log:spin_unlock (&pag->pagb_lock);xfs_log_force (pag_mount (pag),XFS_LOG_SYNC ); -trace_xfs_extent_busy_force (pag, fbno, flen); +trace_xfs_extent_busy_force (pag_group (pag), fbno, flen);spin_lock (&pag->pagb_lock);return false; }
@@ -496,7 +496,8 @@ xfs_extent_busy_trim( out:if (fbno != *bno || flen != *len) { -trace_xfs_extent_busy_trim (args->pag, *bno, *len, fbno, flen); +trace_xfs_extent_busy_trim (pag_group (args->pag), *bno, *len, + fbno, flen); *bno = fbno; *len = flen; *busy_gen = args->pag->pagb_gen;
@@ -525,7 +526,8 @@ xfs_extent_busy_clear_one( busyp->flags =XFS_EXTENT_BUSY_DISCARDED ;return false; } -trace_xfs_extent_busy_clear (pag, busyp->bno, busyp->length); +trace_xfs_extent_busy_clear (pag_group (pag), busyp->bno, + busyp->length);rb_erase (&busyp->rb_node, &pag->pagb_tree); }
fs/xfs/xfs_trace.h +21 -13
@@ -1678,43 +1678,48 @@ TRACE_EVENT(xfs_bunmap, );DECLARE_EVENT_CLASS (xfs_extent_busy_class, - TP_PROTO(const struct xfs_perag *pag, xfs_agblock_t agbno, + TP_PROTO(const struct xfs_group *xg, xfs_agblock_t agbno, xfs_extlen_t len), -TP_ARGS (pag, agbno, len), +TP_ARGS (xg, agbno, len),TP_STRUCT__entry ( __field(dev_t, dev) + __field(enum xfs_group_type, type) __field(xfs_agnumber_t, agno) __field(xfs_agblock_t, agbno)__field (xfs_extlen_t, len) ),TP_fast_assign ( - __entry->dev = pag_mount(pag)->m_super->s_dev; - __entry->agno = pag_agno(pag); + __entry->dev = xg->xg_mount->m_super->s_dev; + __entry->type = xg->xg_type; + __entry->agno = xg->xg_gno; __entry->agbno = agbno; __entry->len = len; ), -TP_printk ("dev %d:%d agno 0x%x agbno 0x%x fsbcount 0x%x" , +TP_printk ("dev %d:%d %sno 0x%x %sbno 0x%x fsbcount 0x%x" ,MAJOR (__entry->dev),MINOR (__entry->dev), +__print_symbolic (__entry->type,XG_TYPE_STRINGS ), __entry->agno, +__print_symbolic (__entry->type,XG_TYPE_STRINGS ), __entry->agbno, __entry->len) );#define DEFINE_BUSY_EVENT (name) \ DEFINE_EVENT(xfs_extent_busy_class, name, \ - TP_PROTO(const struct xfs_perag *pag, xfs_agblock_t agbno, \ - xfs_extlen_t len), \ - TP_ARGS(pag, agbno, len)) + TP_PROTO(const struct xfs_group *xg, xfs_agblock_t agbno, \ + xfs_extlen_t len), \ + TP_ARGS(xg, agbno, len))DEFINE_BUSY_EVENT (xfs_extent_busy);DEFINE_BUSY_EVENT (xfs_extent_busy_force);DEFINE_BUSY_EVENT (xfs_extent_busy_reuse);DEFINE_BUSY_EVENT (xfs_extent_busy_clear); TRACE_EVENT(xfs_extent_busy_trim, - TP_PROTO(const struct xfs_perag *pag, xfs_agblock_t agbno, + TP_PROTO(const struct xfs_group *xg, xfs_agblock_t agbno, xfs_extlen_t len, xfs_agblock_t tbno, xfs_extlen_t tlen), - TP_ARGS(pag, agbno, len, tbno, tlen), + TP_ARGS(xg, agbno, len, tbno, tlen), TP_STRUCT__entry( __field(dev_t, dev) + __field(enum xfs_group_type, type) __field(xfs_agnumber_t, agno) __field(xfs_agblock_t, agbno) __field(xfs_extlen_t, len)
@@ -1722,16 +1727,19 @@ TRACE_EVENT(xfs_extent_busy_trim,__field (xfs_extlen_t, tlen) ),TP_fast_assign ( - __entry->dev = pag_mount(pag)->m_super->s_dev; - __entry->agno =pag_agno (pag); + __entry->dev = xg->xg_mount->m_super->s_dev; + __entry->type = xg->xg_type; + __entry->agno = xg->xg_gno; __entry->agbno = agbno; __entry->len = len; __entry->tbno = tbno; __entry->tlen = tlen; ), - TP_printk("dev %d:%d agno 0x%x agbno 0x%x fsbcount 0x%x found_agbno 0x%x found_fsbcount 0x%x", + TP_printk("dev %d:%d %sno 0x%x %sbno 0x%x fsbcount 0x%x found_agbno 0x%x found_fsbcount 0x%x", MAJOR(__entry->dev), MINOR(__entry->dev), + __print_symbolic(__entry->type, XG_TYPE_STRINGS), __entry->agno, + __print_symbolic(__entry->type, XG_TYPE_STRINGS), __entry->agbno, __entry->len, __entry->tbno,
PATCH 11/16 xfs: convert busy extent tracking to the generic group structure
In reply to Darrick J. WongFrom: Christoph Hellwig <[email protected]>
Split busy extent tracking from struct xfs_perag into its own private structure, which can be pointed to by the generic group structure.
Note that this structure is now dynamically allocated instead of embedded as the upcoming zone XFS code doesn't need it and will also have an unusually high number of groups due to hardware constraints. Dynamically allocating the structure this is a big memory saver for this case.
--- fs/xfs/libxfs/xfs_ag.c | 3 - fs/xfs/libxfs/xfs_ag.h | 5 - fs/xfs/libxfs/xfs_alloc.c | 29 +++--- fs/xfs/libxfs/xfs_alloc_btree.c | 4 - fs/xfs/libxfs/xfs_group.c | 16 +++ fs/xfs/libxfs/xfs_group.h | 5 + fs/xfs/libxfs/xfs_rmap_btree.c | 4 - fs/xfs/scrub/alloc_repair.c | 9 +- fs/xfs/scrub/reap.c | 2 fs/xfs/xfs_discard.c | 10 +- fs/xfs/xfs_extent_busy.c | 198 +++++++++++++++++++++++---------------- fs/xfs/xfs_extent_busy.h | 59 ++++-------- 12 files changed, 193 insertions(+), 151 deletions(-)
fs/xfs/libxfs/xfs_ag.c +0 -3
@@ -230,11 +230,8 @@ xfs_perag_alloc(#ifdef __KERNEL__/* Place kernel structure only init below this point. */ spin_lock_init (&pag->pag_ici_lock); -spin_lock_init (&pag->pagb_lock);INIT_DELAYED_WORK (&pag->pag_blockgc_work, xfs_blockgc_worker);INIT_RADIX_TREE (&pag->pag_ici_root,GFP_ATOMIC ); -init_waitqueue_head (&pag->pagb_wait); - pag->pagb_tree =RB_ROOT ;#endif /* __KERNEL__ */ error =xfs_buf_cache_init (&pag->pag_bcache);
fs/xfs/libxfs/xfs_ag.h +0 -5
@@ -80,11 +80,6 @@ struct xfs_perag {uint8_t pagf_repair_rmap_level;#endif -spinlock_t pagb_lock;/* lock for pagb_tree */ -struct rb_root pagb_tree;/* ordered tree of busy extents */ -unsigned int pagb_gen;/* generation count for pagb_tree */ -wait_queue_head_t pagb_wait;/* woken when pagb_gen changes */ -atomic_t pagf_fstrms;/* # of filestreams active in this AG */ spinlock_t pag_ici_lock;/* incore inode cache lock */
fs/xfs/libxfs/xfs_alloc.c +17 -12
@@ -331,7 +331,8 @@ xfs_alloc_compute_aligned(bool busy;/* Trim busy sections out of found extent */ - busy =xfs_extent_busy_trim (args, &bno, &len, busy_gen); + busy =xfs_extent_busy_trim (pag_group (args->pag), args->minlen, + args->maxlen, &bno, &len, busy_gen);/* * If we have a largish extent that happens to start before min_agbno,
@@ -1251,7 +1252,7 @@ xfs_alloc_ag_vextent_small(if (fbno ==NULLAGBLOCK ) goto out; -xfs_extent_busy_reuse (args->pag, fbno,1 , +xfs_extent_busy_reuse (pag_group (args->pag), fbno,1 , (args->datatype &XFS_ALLOC_NOBUSY ));if (args->datatype &XFS_ALLOC_USERDATA ) {
@@ -1364,7 +1365,8 @@ xfs_alloc_ag_vextent_exact(*/ tbno = fbno; tlen = flen; -xfs_extent_busy_trim (args, &tbno, &tlen, &busy_gen); +xfs_extent_busy_trim (pag_group (args->pag), args->minlen, args->maxlen, + &tbno, &tlen, &busy_gen);/* * Give up if the start of the extent is busy, or the freespace isn't
@@ -1757,8 +1759,9 @@ xfs_alloc_ag_vextent_near(* the allocation can be retried. */ trace_xfs_alloc_near_busy (args); - error =xfs_extent_busy_flush (args->tp, args->pag, - acur.busy_gen, alloc_flags); + error =xfs_extent_busy_flush (args->tp, +pag_group (args->pag), acur.busy_gen, + alloc_flags);if (error) goto out;
@@ -1873,8 +1876,9 @@ xfs_alloc_ag_vextent_size(* the allocation can be retried. */ trace_xfs_alloc_size_busy (args); - error =xfs_extent_busy_flush (args->tp, args->pag, - busy_gen, alloc_flags); + error =xfs_extent_busy_flush (args->tp, +pag_group (args->pag), busy_gen, + alloc_flags);if (error) goto error0;
@@ -1972,8 +1976,9 @@ xfs_alloc_ag_vextent_size(* the allocation can be retried. */ trace_xfs_alloc_size_busy (args); - error =xfs_extent_busy_flush (args->tp, args->pag, - busy_gen, alloc_flags); + error =xfs_extent_busy_flush (args->tp, +pag_group (args->pag), busy_gen, + alloc_flags);if (error) goto error0;
@@ -3615,8 +3620,8 @@ xfs_alloc_vextent_finish(if (error) goto out_drop_perag; -ASSERT (!xfs_extent_busy_search (args->pag, args->agbno, - args->len)); +ASSERT (!xfs_extent_busy_search (pag_group (args->pag), + args->agbno, args->len)); }xfs_ag_resv_alloc_extent (args->pag, args->resv, args);
@@ -4014,7 +4019,7 @@ __xfs_free_extent(if (skip_discard) busy_flags |=XFS_EXTENT_BUSY_SKIP_DISCARD ; -xfs_extent_busy_insert (tp, pag, agbno, len, busy_flags); +xfs_extent_busy_insert (tp,pag_group (pag), agbno, len, busy_flags);return 0 ; err_release:
fs/xfs/libxfs/xfs_alloc_btree.c +2 -2
@@ -86,7 +86,7 @@ xfs_allocbt_alloc_block( }atomic64_inc (&cur->bc_mp->m_allocbt_blks); -xfs_extent_busy_reuse (cur->bc_ag.pag, bno,1 , false); +xfs_extent_busy_reuse (pag_group (cur->bc_ag.pag), bno,1 , false); new->s =cpu_to_be32 (bno);
@@ -110,7 +110,7 @@ xfs_allocbt_free_block(return error;atomic64_dec (&cur->bc_mp->m_allocbt_blks); -xfs_extent_busy_insert (cur->bc_tp, agbp->b_pag, bno,1 , +xfs_extent_busy_insert (cur->bc_tp,pag_group (agbp->b_pag), bno,1 ,XFS_EXTENT_BUSY_SKIP_DISCARD );return 0 ; }
fs/xfs/libxfs/xfs_group.c +14 -2
@@ -10,6 +10,7 @@#include "xfs_mount.h" #include "xfs_error.h" #include "xfs_trace.h" +#include "xfs_extent_busy.h" #include "xfs_group.h" /*
@@ -161,6 +162,9 @@ xfs_group_free(XFS_IS_CORRUPT (mp,atomic_read (&xg->xg_ref) !=0 );xfs_defer_drain_free (&xg->xg_intents_drain); +#ifdef __KERNEL__ +kfree (xg->xg_busy_extents); +#endif if (uninit)uninit (xg);
@@ -185,6 +189,9 @@ xfs_group_insert( xg->xg_type = type;#ifdef __KERNEL__ + xg->xg_busy_extents =xfs_extent_busy_alloc (); +if (!xg->xg_busy_extents) +return -ENOMEM ;spin_lock_init (&xg->xg_state_lock);xfs_hooks_init (&xg->xg_rmap_update_hooks);#endif
@@ -196,9 +203,14 @@ xfs_group_insert( error =xa_insert (&mp->m_groups[type].xa, index, xg,GFP_KERNEL );if (error) {WARN_ON_ONCE (error == -EBUSY ); -xfs_defer_drain_free (&xg->xg_intents_drain); -return error; + goto out_drain; }return 0 ; +out_drain: +xfs_defer_drain_free (&xg->xg_intents_drain); +#ifdef __KERNEL__ +kfree (xg->xg_busy_extents); +#endif +return error; }
fs/xfs/libxfs/xfs_group.h +5 -0
@@ -15,6 +15,11 @@ struct xfs_group {#ifdef __KERNEL__/* -- kernel only structures below this line -- */ +/* +* Track freed but not yet committed extents. +*/ +struct xfs_extent_busy_tree *xg_busy_extents; +/* * Bitsets of per-ag metadata that have been checked and/or are sick. * Callers should hold xg_state_lock before accessing this field.
fs/xfs/libxfs/xfs_rmap_btree.c +2 -2
@@ -102,7 +102,7 @@ xfs_rmapbt_alloc_block(return 0 ; } -xfs_extent_busy_reuse (pag, bno,1 , false); +xfs_extent_busy_reuse (pag_group (pag), bno,1 , false); new->s =cpu_to_be32 (bno);be32_add_cpu (&agf->agf_rmap_blocks,1 );
@@ -136,7 +136,7 @@ xfs_rmapbt_free_block(if (error)return error; -xfs_extent_busy_insert (cur->bc_tp, pag, bno,1 , +xfs_extent_busy_insert (cur->bc_tp,pag_group (pag), bno,1 ,XFS_EXTENT_BUSY_SKIP_DISCARD );xfs_ag_resv_free_extent (pag,XFS_AG_RESV_RMAPBT ,NULL ,1 );
fs/xfs/scrub/alloc_repair.c +6 -3
@@ -132,13 +132,16 @@ intxrep_setup_ag_allocbt ( struct xfs_scrub *sc) { +struct xfs_group *xg =pag_group (sc->sa.pag); +unsigned int busy_gen; +/* * Make sure the busy extent list is clear because we can't put extents * on there twice. */ -if (xfs_extent_busy_list_empty (sc->sa.pag, &busy_gen)) +if (xfs_extent_busy_list_empty (xg, &busy_gen))return 0 ; -return xfs_extent_busy_flush (sc->tp, sc->sa.pag, busy_gen,0 ); +return xfs_extent_busy_flush (sc->tp, xg, busy_gen,0 ); }/* Check for any obvious conflicts in the free extent. */
@@ -866,7 +869,7 @@ xrep_allocbt(* on there twice. In theory we cleared this before we started, but * let's not risk the filesystem. */ -if (!xfs_extent_busy_list_empty (sc->sa.pag, &busy_gen)) { +if (!xfs_extent_busy_list_empty (pag_group (sc->sa.pag), &busy_gen)) { error = -EDEADLOCK ; goto out_ra; }
fs/xfs/scrub/reap.c +1 -1
@@ -137,7 +137,7 @@ xreap_put_freelist( agfl_bp, agbno, 0);if (error)return error; -xfs_extent_busy_insert (sc->tp, sc->sa.pag, agbno,1 , +xfs_extent_busy_insert (sc->tp,pag_group (sc->sa.pag), agbno,1 ,XFS_EXTENT_BUSY_SKIP_DISCARD );return 0 ;
fs/xfs/xfs_discard.c +6 -4
@@ -117,10 +117,12 @@ xfs_discard_extents(blk_start_plug (&plug);list_for_each_entry (busyp, &extents->extent_list, list) { -trace_xfs_discard_extent (busyp->pag, busyp->bno, busyp->length); +struct xfs_perag *pag =to_perag (busyp->group); + +trace_xfs_discard_extent (pag, busyp->bno, busyp->length); error =__blkdev_issue_discard (mp->m_ddev_targp->bt_bdev, -xfs_agbno_to_daddr (busyp->pag, busyp->bno), +xfs_agbno_to_daddr (pag, busyp->bno),XFS_FSB_TO_BB (mp, busyp->length),GFP_KERNEL , &bio);if (error && error != -EOPNOTSUPP ) {
@@ -271,12 +273,12 @@ xfs_trim_gather_extents(* If any blocks in the range are still busy, skip the * discard and try again the next time. */ -if (xfs_extent_busy_search (pag, fbno, flen)) { +if (xfs_extent_busy_search (pag_group (pag), fbno, flen)) {trace_xfs_discard_busy (pag, fbno, flen); goto next_extent; } -xfs_extent_busy_insert_discard (pag, fbno, flen, +xfs_extent_busy_insert_discard (pag_group (pag), fbno, flen, &extents->extent_list); next_extent:if (tcur->by_bno)
fs/xfs/xfs_extent_busy.c +119 -79
461 lines not on this page · raw message
fs/xfs/xfs_extent_busy.h +21 -38
85 lines not on this page · raw message
PATCH 12/16 xfs: add a generic group pointer to the btree cursor
In reply to Darrick J. WongFrom: Christoph Hellwig <[email protected]>
Replace the pag pointers in the type specific union with a generic xfs_group pointer. This prepares for adding realtime group support.
--- fs/xfs/libxfs/xfs_alloc.c | 8 ++++---- fs/xfs/libxfs/xfs_alloc_btree.c | 28 ++++++++++++++-------------- fs/xfs/libxfs/xfs_btree.c | 35 ++++++++++++----------------------- fs/xfs/libxfs/xfs_btree.h | 3 +-- fs/xfs/libxfs/xfs_btree_mem.c | 6 ++---- fs/xfs/libxfs/xfs_ialloc.c | 12 +++++++----- fs/xfs/libxfs/xfs_ialloc_btree.c | 15 ++++++++------- fs/xfs/libxfs/xfs_refcount.c | 17 +++++++++-------- fs/xfs/libxfs/xfs_refcount_btree.c | 10 +++++----- fs/xfs/libxfs/xfs_rmap.c | 8 +++----- fs/xfs/libxfs/xfs_rmap_btree.c | 19 ++++++++++--------- fs/xfs/scrub/alloc.c | 2 +- fs/xfs/scrub/bmap.c | 3 ++- fs/xfs/scrub/bmap_repair.c | 4 ++-- fs/xfs/scrub/cow_repair.c | 9 ++++++--- fs/xfs/scrub/health.c | 2 +- fs/xfs/scrub/ialloc.c | 14 +++++++------- fs/xfs/scrub/refcount.c | 3 ++- fs/xfs/scrub/rmap.c | 2 +- fs/xfs/scrub/rmap_repair.c | 2 +- fs/xfs/xfs_fsmap.c | 6 ++++-- fs/xfs/xfs_health.c | 23 ++++++----------------- fs/xfs/xfs_trace.h | 28 ++++++++++++++-------------- 23 files changed, 122 insertions(+), 137 deletions(-)
fs/xfs/libxfs/xfs_alloc.c +4 -4
@@ -275,7 +275,7 @@ xfs_alloc_complain_bad_rec(xfs_warn (mp,"%sbt record corruption in AG %d detected at %pS!" , - cur->bc_ops->name,pag_agno (cur->bc_ag.pag), fa); + cur->bc_ops->name, cur->bc_group->xg_gno, fa);xfs_warn (mp,"start block 0x%x block count 0x%x" , irec->ar_startblock, irec->ar_blockcount);
@@ -303,7 +303,7 @@ xfs_alloc_get_rec(return error;xfs_alloc_btrec_to_irec (rec, &irec); - fa =xfs_alloc_check_irec (cur->bc_ag.pag, &irec); + fa =xfs_alloc_check_irec (to_perag (cur->bc_group), &irec);if (fa)return xfs_alloc_complain_bad_rec (cur, fa, &irec);
@@ -540,7 +540,7 @@ static intxfs_alloc_fixup_longest ( struct xfs_btree_cur *cnt_cur) { -struct xfs_perag *pag = cnt_cur->bc_ag.pag; +struct xfs_perag *pag =to_perag (cnt_cur->bc_group);struct xfs_buf *bp = cnt_cur->bc_ag.agbp;struct xfs_agf *agf = bp->b_addr;xfs_extlen_t longest =0 ;
@@ -4044,7 +4044,7 @@ xfs_alloc_query_range_helper(xfs_failaddr_t fa;xfs_alloc_btrec_to_irec (rec, &irec); - fa =xfs_alloc_check_irec (cur->bc_ag.pag, &irec); + fa =xfs_alloc_check_irec (to_perag (cur->bc_group), &irec);if (fa)return xfs_alloc_complain_bad_rec (cur, fa, &irec);
fs/xfs/libxfs/xfs_alloc_btree.c +14 -14
@@ -28,7 +28,7 @@ xfs_bnobt_dup_cursor( struct xfs_btree_cur *cur) {return xfs_bnobt_init_cursor (cur->bc_mp, cur->bc_tp, cur->bc_ag.agbp, - cur->bc_ag.pag); +to_perag (cur->bc_group)); } STATIC struct xfs_btree_cur *
@@ -36,29 +36,29 @@ xfs_cntbt_dup_cursor( struct xfs_btree_cur *cur) {return xfs_cntbt_init_cursor (cur->bc_mp, cur->bc_tp, cur->bc_ag.agbp, - cur->bc_ag.pag); +to_perag (cur->bc_group)); } - STATIC voidxfs_allocbt_set_root (struct xfs_btree_cur *cur,const union xfs_btree_ptr *ptr,int inc) { -struct xfs_buf *agbp = cur->bc_ag.agbp; -struct xfs_agf *agf = agbp->b_addr; +struct xfs_perag *pag =to_perag (cur->bc_group); +struct xfs_buf *agbp = cur->bc_ag.agbp; +struct xfs_agf *agf = agbp->b_addr;ASSERT (ptr->s !=0 );if (xfs_btree_is_bno (cur->bc_ops)) { agf->agf_bno_root = ptr->s;be32_add_cpu (&agf->agf_bno_level, inc); - cur->bc_ag.pag->pagf_bno_level += inc; + pag->pagf_bno_level += inc; }else { agf->agf_cnt_root = ptr->s;be32_add_cpu (&agf->agf_cnt_level, inc); - cur->bc_ag.pag->pagf_cnt_level += inc; + pag->pagf_cnt_level += inc; }xfs_alloc_log_agf (cur->bc_tp, agbp,XFS_AGF_ROOTS |XFS_AGF_LEVELS );
@@ -75,7 +75,7 @@ xfs_allocbt_alloc_block(xfs_agblock_t bno;/* Allocate the new block from the freelist. If we can't, give up. */ - error =xfs_alloc_get_freelist (cur->bc_ag.pag, cur->bc_tp, + error =xfs_alloc_get_freelist (to_perag (cur->bc_group), cur->bc_tp, cur->bc_ag.agbp, &bno,1 );if (error)return error;
@@ -86,7 +86,7 @@ xfs_allocbt_alloc_block( }atomic64_inc (&cur->bc_mp->m_allocbt_blks); -xfs_extent_busy_reuse (pag_group (cur->bc_ag.pag), bno,1 , false); +xfs_extent_busy_reuse (cur->bc_group, bno,1 , false); new->s =cpu_to_be32 (bno);
@@ -104,8 +104,8 @@ xfs_allocbt_free_block(int error; bno =xfs_daddr_to_agbno (cur->bc_mp,xfs_buf_daddr (bp)); - error =xfs_alloc_put_freelist (cur->bc_ag.pag, cur->bc_tp, agbp,NULL , - bno,1 ); + error =xfs_alloc_put_freelist (to_perag (cur->bc_group), cur->bc_tp, + agbp,NULL , bno,1 );if (error)return error;
@@ -178,7 +178,7 @@ xfs_allocbt_init_ptr_from_cur( {struct xfs_agf *agf = cur->bc_ag.agbp->b_addr; -ASSERT (pag_agno (cur->bc_ag.pag) ==be32_to_cpu (agf->agf_seqno)); +ASSERT (cur->bc_group->xg_gno ==be32_to_cpu (agf->agf_seqno));if (xfs_btree_is_bno (cur->bc_ops)) ptr->s = agf->agf_bno_root;
@@ -492,7 +492,7 @@ xfs_bnobt_init_cursor( cur =xfs_btree_alloc_cursor (mp, tp, &xfs_bnobt_ops, mp->m_alloc_maxlevels, xfs_allocbt_cur_cache); - cur->bc_ag.pag =xfs_perag_hold (pag); + cur->bc_group =xfs_group_hold (pag_group (pag)); cur->bc_ag.agbp = agbp;if (agbp) {struct xfs_agf *agf = agbp->b_addr;
@@ -518,7 +518,7 @@ xfs_cntbt_init_cursor( cur =xfs_btree_alloc_cursor (mp, tp, &xfs_cntbt_ops, mp->m_alloc_maxlevels, xfs_allocbt_cur_cache); - cur->bc_ag.pag =xfs_perag_hold (pag); + cur->bc_group =xfs_group_hold (pag_group (pag)); cur->bc_ag.agbp = agbp;if (agbp) {struct xfs_agf *agf = agbp->b_addr;
fs/xfs/libxfs/xfs_btree.c +12 -23
@@ -225,7 +225,7 @@ __xfs_btree_check_agblock( struct xfs_buf *bp) {struct xfs_mount *mp = cur->bc_mp; -struct xfs_perag *pag = cur->bc_ag.pag; +struct xfs_perag *pag =to_perag (cur->bc_group);xfs_failaddr_t fa;xfs_agblock_t agbno;
@@ -331,7 +331,7 @@ __xfs_btree_check_ptr(return -EFSCORRUPTED ;break ;case XFS_BTREE_TYPE_AG : -if (!xfs_verify_agbno (cur->bc_ag.pag, +if (!xfs_verify_agbno (to_perag (cur->bc_group),be32_to_cpu ((&ptr->s)[index])))return -EFSCORRUPTED ;break ;
@@ -372,7 +372,7 @@ xfs_btree_check_ptr(case XFS_BTREE_TYPE_AG :xfs_err (cur->bc_mp,"AG %u: Corrupt %sbt pointer at level %d index %d." , -pag_agno (cur->bc_ag.pag), cur->bc_ops->name, + cur->bc_group->xg_gno, cur->bc_ops->name, level, index);break ; }
@@ -523,20 +523,8 @@ xfs_btree_del_cursor(ASSERT (!xfs_btree_is_bmap (cur->bc_ops) || cur->bc_bmap.allocated ==0 ||xfs_is_shutdown (cur->bc_mp) || error !=0 ); -switch (cur->bc_ops->type) { -case XFS_BTREE_TYPE_AG : -if (cur->bc_ag.pag) -xfs_perag_put (cur->bc_ag.pag); -break ; -case XFS_BTREE_TYPE_INODE : -/* nothing to do */ -break ; -case XFS_BTREE_TYPE_MEM : -if (cur->bc_mem.pag) -xfs_perag_put (cur->bc_mem.pag); -break ; - } - +if (cur->bc_group) +xfs_group_put (cur->bc_group);kmem_cache_free (cur->bc_cache, cur); }
@@ -1017,21 +1005,22 @@ xfs_btree_readahead_agblock( struct xfs_btree_block *block) {struct xfs_mount *mp = cur->bc_mp; +struct xfs_perag *pag =to_perag (cur->bc_group);xfs_agblock_t left =be32_to_cpu (block->bb_u.s.bb_leftsib);xfs_agblock_t right =be32_to_cpu (block->bb_u.s.bb_rightsib);int rval =0 ;if ((lr &XFS_BTCUR_LEFTRA ) && left !=NULLAGBLOCK ) {xfs_buf_readahead (mp->m_ddev_targp, -xfs_agbno_to_daddr (cur->bc_ag.pag, left), - mp->m_bsize, cur->bc_ops->buf_ops); +xfs_agbno_to_daddr (pag, left), mp->m_bsize, + cur->bc_ops->buf_ops); rval++; }if ((lr &XFS_BTCUR_RIGHTRA ) && right !=NULLAGBLOCK ) {xfs_buf_readahead (mp->m_ddev_targp, -xfs_agbno_to_daddr (cur->bc_ag.pag, right), - mp->m_bsize, cur->bc_ops->buf_ops); +xfs_agbno_to_daddr (pag, right), mp->m_bsize, + cur->bc_ops->buf_ops); rval++; }
@@ -1090,7 +1079,7 @@ xfs_btree_ptr_to_daddr(switch (cur->bc_ops->type) {case XFS_BTREE_TYPE_AG : - *daddr =xfs_agbno_to_daddr (cur->bc_ag.pag, + *daddr =xfs_agbno_to_daddr (to_perag (cur->bc_group),be32_to_cpu (ptr->s));break ;case XFS_BTREE_TYPE_INODE :
@@ -1312,7 +1301,7 @@ xfs_btree_owner(case XFS_BTREE_TYPE_INODE :return cur->bc_ino.ip->i_ino;case XFS_BTREE_TYPE_AG : -return pag_agno (cur->bc_ag.pag); +return cur->bc_group->xg_gno;default :ASSERT (0 );return 0 ;
fs/xfs/libxfs/xfs_btree.h +1 -2
@@ -254,6 +254,7 @@ struct xfs_btree_curunion xfs_btree_irec bc_rec;/* current insert/search record value */ uint8_t bc_nlevels;/* number of levels in the tree */ uint8_t bc_maxlevels;/* maximum levels for this btree type */ +struct xfs_group *bc_group;/* per-type information */ union {
@@ -264,13 +265,11 @@ struct xfs_btree_curstruct xbtree_ifakeroot *ifake;/* for staging cursor */ } bc_ino;struct { -struct xfs_perag *pag;struct xfs_buf *agbp;struct xbtree_afakeroot *afake;/* for staging cursor */ } bc_ag;struct {struct xfbtree *xfbtree; -struct xfs_perag *pag; } bc_mem; };
fs/xfs/libxfs/xfs_btree_mem.c +2 -4
@@ -57,10 +57,8 @@ xfbtree_dup_cursor( ncur->bc_flags = cur->bc_flags; ncur->bc_nlevels = cur->bc_nlevels; ncur->bc_mem.xfbtree = cur->bc_mem.xfbtree; - -if (cur->bc_mem.pag) - ncur->bc_mem.pag =xfs_perag_hold (cur->bc_mem.pag); - +if (cur->bc_group) + ncur->bc_group =xfs_group_hold (cur->bc_group);return ncur; }
fs/xfs/libxfs/xfs_ialloc.c +7 -5
@@ -142,7 +142,7 @@ xfs_inobt_complain_bad_rec(xfs_warn (mp,"%sbt record corruption in AG %d detected at %pS!" , - cur->bc_ops->name,pag_agno (cur->bc_ag.pag), fa); + cur->bc_ops->name, cur->bc_group->xg_gno, fa); xfs_warn(mp, "start inode 0x%x, count 0x%x, free 0x%x freemask 0x%llx, holemask 0x%x", irec->ir_startino, irec->ir_count, irec->ir_freecount,
@@ -170,7 +170,7 @@ xfs_inobt_get_rec(return error;xfs_inobt_btrec_to_irec (mp, rec, irec); - fa =xfs_inobt_check_irec (cur->bc_ag.pag, irec); + fa =xfs_inobt_check_irec (to_perag (cur->bc_group), irec);if (fa)return xfs_inobt_complain_bad_rec (cur, fa, irec);
@@ -275,8 +275,10 @@ xfs_check_agi_freecount( } }while (i ==1 ); -if (!xfs_is_shutdown (cur->bc_mp)) -ASSERT (freecount == cur->bc_ag.pag->pagi_freecount); +if (!xfs_is_shutdown (cur->bc_mp)) { +ASSERT (freecount == +to_perag (cur->bc_group)->pagi_freecount); + } }return 0 ; }
@@ -2880,7 +2882,7 @@ xfs_ialloc_count_inodes_rec(xfs_failaddr_t fa;xfs_inobt_btrec_to_irec (cur->bc_mp, rec, &irec); - fa =xfs_inobt_check_irec (cur->bc_ag.pag, &irec); + fa =xfs_inobt_check_irec (to_perag (cur->bc_group), &irec);if (fa)return xfs_inobt_complain_bad_rec (cur, fa, &irec);
fs/xfs/libxfs/xfs_ialloc_btree.c +8 -7
@@ -37,7 +37,7 @@ STATIC struct xfs_btree_cur *xfs_inobt_dup_cursor ( struct xfs_btree_cur *cur) { -return xfs_inobt_init_cursor (cur->bc_ag.pag, cur->bc_tp, +return xfs_inobt_init_cursor (to_perag (cur->bc_group), cur->bc_tp, cur->bc_ag.agbp); }
@@ -45,7 +45,7 @@ STATIC struct xfs_btree_cur *xfs_finobt_dup_cursor ( struct xfs_btree_cur *cur) { -return xfs_finobt_init_cursor (cur->bc_ag.pag, cur->bc_tp, +return xfs_finobt_init_cursor (to_perag (cur->bc_group), cur->bc_tp, cur->bc_ag.agbp); }
@@ -112,7 +112,7 @@ __xfs_inobt_alloc_block(memset (&args,0 ,sizeof (args)); args.tp = cur->bc_tp; args.mp = cur->bc_mp; - args.pag = cur->bc_ag.pag; + args.pag =to_perag (cur->bc_group); args.oinfo =XFS_RMAP_OINFO_INOBT ; args.minlen =1 ; args.maxlen =1 ;
@@ -248,7 +248,7 @@ xfs_inobt_init_ptr_from_cur( {struct xfs_agi *agi = cur->bc_ag.agbp->b_addr; -ASSERT (pag_agno (cur->bc_ag.pag) ==be32_to_cpu (agi->agi_seqno)); +ASSERT (cur->bc_group->xg_gno ==be32_to_cpu (agi->agi_seqno)); ptr->s = agi->agi_root; }
@@ -260,7 +260,8 @@ xfs_finobt_init_ptr_from_cur( {struct xfs_agi *agi = cur->bc_ag.agbp->b_addr; -ASSERT (pag_agno (cur->bc_ag.pag) ==be32_to_cpu (agi->agi_seqno)); +ASSERT (cur->bc_group->xg_gno ==be32_to_cpu (agi->agi_seqno)); + ptr->s = agi->agi_free_root; }
@@ -483,7 +484,7 @@ xfs_inobt_init_cursor( cur =xfs_btree_alloc_cursor (mp, tp, &xfs_inobt_ops,M_IGEO (mp)->inobt_maxlevels, xfs_inobt_cur_cache); - cur->bc_ag.pag =xfs_perag_hold (pag); + cur->bc_group =xfs_group_hold (pag_group (pag)); cur->bc_ag.agbp = agbp;if (agbp) {struct xfs_agi *agi = agbp->b_addr;
@@ -509,7 +510,7 @@ xfs_finobt_init_cursor( cur =xfs_btree_alloc_cursor (mp, tp, &xfs_finobt_ops,M_IGEO (mp)->inobt_maxlevels, xfs_inobt_cur_cache); - cur->bc_ag.pag =xfs_perag_hold (pag); + cur->bc_group =xfs_group_hold (pag_group (pag)); cur->bc_ag.agbp = agbp;if (agbp) {struct xfs_agi *agi = agbp->b_addr;
fs/xfs/libxfs/xfs_refcount.c +9 -8
@@ -154,7 +154,7 @@ xfs_refcount_complain_bad_rec(xfs_warn (mp,"Refcount BTree record corruption in AG %d detected at %pS!" , -pag_agno (cur->bc_ag.pag), fa); + cur->bc_group->xg_gno, fa);xfs_warn (mp,"Start block 0x%x, block count 0x%x, references 0x%x" , irec->rc_startblock, irec->rc_blockcount, irec->rc_refcount);
@@ -180,7 +180,7 @@ xfs_refcount_get_rec(return error;xfs_refcount_btrec_to_irec (rec, irec); - fa =xfs_refcount_check_irec (cur->bc_ag.pag, irec); + fa =xfs_refcount_check_irec (to_perag (cur->bc_group), irec);if (fa)return xfs_refcount_complain_bad_rec (cur, fa, irec);
@@ -1154,7 +1154,7 @@ xfs_refcount_adjust_extents( goto out_error; } }else { - fsbno =xfs_agbno_to_fsb (cur->bc_ag.pag, + fsbno =xfs_agbno_to_fsb (to_perag (cur->bc_group), tmp.rc_startblock); error = xfs_free_extent_later(cur->bc_tp, fsbno, tmp.rc_blockcount, NULL,
@@ -1216,7 +1216,7 @@ xfs_refcount_adjust_extents( } goto advloop; }else { - fsbno =xfs_agbno_to_fsb (cur->bc_ag.pag, + fsbno =xfs_agbno_to_fsb (to_perag (cur->bc_group), ext.rc_startblock); error = xfs_free_extent_later(cur->bc_tp, fsbno, ext.rc_blockcount, NULL,
@@ -1310,7 +1310,7 @@ xfs_refcount_continue_op( xfs_agblock_t new_agbno) {struct xfs_mount *mp = cur->bc_mp; -struct xfs_perag *pag = cur->bc_ag.pag; +struct xfs_perag *pag =to_perag (cur->bc_group);if (XFS_IS_CORRUPT (mp, !xfs_verify_agbext (pag, new_agbno, ri->ri_blockcount))) {
@@ -1358,7 +1358,7 @@ xfs_refcount_finish_one(* If we haven't gotten a cursor or the cursor AG doesn't match * the startblock, get one now. */ -if (rcur !=NULL && rcur->bc_ag.pag != ri->ri_pag) { +if (rcur !=NULL &&to_perag (rcur->bc_group) != ri->ri_pag) { nr_ops = rcur->bc_refc.nr_ops; shape_changes = rcur->bc_refc.shape_changes;xfs_btree_del_cursor (rcur,0 );
@@ -1878,7 +1878,8 @@ xfs_refcount_recover_extent(INIT_LIST_HEAD (&rr->rr_list);xfs_refcount_btrec_to_irec (rec, &rr->rr_rrec); -if (xfs_refcount_check_irec (cur->bc_ag.pag, &rr->rr_rrec) !=NULL || +if (xfs_refcount_check_irec (to_perag (cur->bc_group), &rr->rr_rrec) != +NULL ||XFS_IS_CORRUPT (cur->bc_mp, rr->rr_rrec.rc_domain !=XFS_REFC_DOMAIN_COW )) {xfs_btree_mark_sick (cur);
@@ -2026,7 +2027,7 @@ xfs_refcount_query_range_helper(xfs_failaddr_t fa;xfs_refcount_btrec_to_irec (rec, &irec); - fa =xfs_refcount_check_irec (cur->bc_ag.pag, &irec); + fa =xfs_refcount_check_irec (to_perag (cur->bc_group), &irec);if (fa)return xfs_refcount_complain_bad_rec (cur, fa, &irec);
fs/xfs/libxfs/xfs_refcount_btree.c +5 -5
@@ -30,7 +30,7 @@ xfs_refcountbt_dup_cursor( struct xfs_btree_cur *cur) {return xfs_refcountbt_init_cursor (cur->bc_mp, cur->bc_tp, - cur->bc_ag.agbp, cur->bc_ag.pag); + cur->bc_ag.agbp,to_perag (cur->bc_group)); }STATIC void
@@ -68,7 +68,7 @@ xfs_refcountbt_alloc_block(memset (&args,0 ,sizeof (args)); args.tp = cur->bc_tp; args.mp = cur->bc_mp; - args.pag = cur->bc_ag.pag; + args.pag =to_perag (cur->bc_group); args.oinfo =XFS_RMAP_OINFO_REFC ; args.minlen = args.maxlen = args.prod =1 ; args.resv =XFS_AG_RESV_METADATA ;
@@ -81,7 +81,7 @@ xfs_refcountbt_alloc_block( *stat =0 ;return 0 ; } -ASSERT (args.agno ==pag_agno (cur->bc_ag.pag)); +ASSERT (args.agno == cur->bc_group->xg_gno);ASSERT (args.len ==1 ); new->s =cpu_to_be32 (args.agbno);
@@ -169,7 +169,7 @@ xfs_refcountbt_init_ptr_from_cur( {struct xfs_agf *agf = cur->bc_ag.agbp->b_addr; -ASSERT (pag_agno (cur->bc_ag.pag) ==be32_to_cpu (agf->agf_seqno)); +ASSERT (cur->bc_group->xg_gno ==be32_to_cpu (agf->agf_seqno)); ptr->s = agf->agf_refcount_root; }
@@ -365,7 +365,7 @@ xfs_refcountbt_init_cursor( cur =xfs_btree_alloc_cursor (mp, tp, &xfs_refcountbt_ops, mp->m_refc_maxlevels, xfs_refcountbt_cur_cache); - cur->bc_ag.pag =xfs_perag_hold (pag); + cur->bc_group =xfs_group_hold (pag_group (pag)); cur->bc_refc.nr_ops =0 ; cur->bc_refc.shape_changes =0 ; cur->bc_ag.agbp = agbp;
fs/xfs/libxfs/xfs_rmap.c +3 -5
@@ -269,9 +269,7 @@ xfs_rmap_check_btrec(struct xfs_btree_cur *cur, const struct xfs_rmap_irec *irec) { - if (xfs_btree_is_mem_rmap(cur->bc_ops)) - return xfs_rmap_check_irec(cur->bc_mem.pag, irec); - return xfs_rmap_check_irec(cur->bc_ag.pag, irec); + return xfs_rmap_check_irec(to_perag(cur->bc_group), irec); } static inline int
@@ -288,7 +286,7 @@ xfs_rmap_complain_bad_rec(else xfs_warn (mp,"Reverse Mapping BTree record corruption in AG %d detected at %pS!" , -pag_agno (cur->bc_ag.pag), fa); + cur->bc_group->xg_gno, fa); xfs_warn(mp, "Owner 0x%llx, flags 0x%x, start block 0x%x block count 0x%x", irec->rm_owner, irec->rm_flags, irec->rm_startblock,
@@ -2588,7 +2586,7 @@ xfs_rmap_finish_one(* If we haven't gotten a cursor or the cursor AG doesn't match * the startblock, get one now. */ -if (rcur !=NULL && rcur->bc_ag.pag != ri->ri_pag) { +if (rcur !=NULL &&to_perag (rcur->bc_group) != ri->ri_pag) {xfs_btree_del_cursor (rcur,0 ); rcur =NULL ; *pcur =NULL ;
fs/xfs/libxfs/xfs_rmap_btree.c +10 -9
@@ -57,7 +57,7 @@ xfs_rmapbt_dup_cursor( struct xfs_btree_cur *cur) {return xfs_rmapbt_init_cursor (cur->bc_mp, cur->bc_tp, - cur->bc_ag.agbp, cur->bc_ag.pag); + cur->bc_ag.agbp,to_perag (cur->bc_group)); }STATIC void
@@ -66,14 +66,15 @@ xfs_rmapbt_set_root( const union xfs_btree_ptr *ptr, int inc) { -struct xfs_buf *agbp = cur->bc_ag.agbp; -struct xfs_agf *agf = agbp->b_addr; +struct xfs_buf *agbp = cur->bc_ag.agbp; +struct xfs_agf *agf = agbp->b_addr; +struct xfs_perag *pag =to_perag (cur->bc_group);ASSERT (ptr->s !=0 ); agf->agf_rmap_root = ptr->s;be32_add_cpu (&agf->agf_rmap_level, inc); - cur->bc_ag.pag->pagf_rmap_level += inc; + pag->pagf_rmap_level += inc;xfs_alloc_log_agf (cur->bc_tp, agbp,XFS_AGF_ROOTS |XFS_AGF_LEVELS ); }
@@ -87,7 +88,7 @@ xfs_rmapbt_alloc_block( {struct xfs_buf *agbp = cur->bc_ag.agbp;struct xfs_agf *agf = agbp->b_addr; -struct xfs_perag *pag = cur->bc_ag.pag; +struct xfs_perag *pag =to_perag (cur->bc_group);struct xfs_alloc_arg args = { .len =1 };int error;xfs_agblock_t bno;
@@ -125,7 +126,7 @@ xfs_rmapbt_free_block( {struct xfs_buf *agbp = cur->bc_ag.agbp;struct xfs_agf *agf = agbp->b_addr; -struct xfs_perag *pag = cur->bc_ag.pag; +struct xfs_perag *pag =to_perag (cur->bc_group);xfs_agblock_t bno;int error;
@@ -227,7 +228,7 @@ xfs_rmapbt_init_ptr_from_cur( {struct xfs_agf *agf = cur->bc_ag.agbp->b_addr; -ASSERT (pag_agno (cur->bc_ag.pag) ==be32_to_cpu (agf->agf_seqno)); +ASSERT (cur->bc_group->xg_gno ==be32_to_cpu (agf->agf_seqno)); ptr->s = agf->agf_rmap_root; }
@@ -538,7 +539,7 @@ xfs_rmapbt_init_cursor( cur =xfs_btree_alloc_cursor (mp, tp, &xfs_rmapbt_ops, mp->m_rmap_maxlevels, xfs_rmapbt_cur_cache); - cur->bc_ag.pag =xfs_perag_hold (pag); + cur->bc_group =xfs_group_hold (pag_group (pag)); cur->bc_ag.agbp = agbp;if (agbp) {struct xfs_agf *agf = agbp->b_addr;
@@ -653,7 +654,7 @@ xfs_rmapbt_mem_cursor( cur->bc_mem.xfbtree = xfbt; cur->bc_nlevels = xfbt->nlevels; - cur->bc_mem.pag =xfs_perag_hold (pag); + cur->bc_group =xfs_group_hold (pag_group (pag));return cur; }
fs/xfs/scrub/alloc.c +1 -1
@@ -139,7 +139,7 @@ xchk_allocbt_rec(struct xchk_alloc *ca = bs->private;xfs_alloc_btrec_to_irec (rec, &irec); -if (xfs_alloc_check_irec (bs->cur->bc_ag.pag, &irec) !=NULL ) { +if (xfs_alloc_check_irec (to_perag (bs->cur->bc_group), &irec) !=NULL ) {xchk_btree_set_corrupt (bs->sc, bs->cur,0 );return 0 ; }
fs/xfs/scrub/bmap.c +2 -1
@@ -601,7 +601,8 @@ xchk_bmap_check_rmap(xchk_fblock_set_corrupt (sc, sbcri->whichfork, check_rec.rm_offset);if (irec.br_startblock != -xfs_agbno_to_fsb (cur->bc_ag.pag, check_rec.rm_startblock)) +xfs_agbno_to_fsb (to_perag (cur->bc_group), + check_rec.rm_startblock))xchk_fblock_set_corrupt (sc, sbcri->whichfork, check_rec.rm_offset);if (irec.br_blockcount > check_rec.rm_blockcount)
fs/xfs/scrub/bmap_repair.c +2 -2
@@ -196,7 +196,7 @@ xrep_bmap_check_fork_rmap(return -EFSCORRUPTED ;/* Check that this is within the AG. */ -if (!xfs_verify_agbext (cur->bc_ag.pag, rec->rm_startblock, +if (!xfs_verify_agbext (to_perag (cur->bc_group), rec->rm_startblock, rec->rm_blockcount))return -EFSCORRUPTED ;
@@ -268,7 +268,7 @@ xrep_bmap_walk_rmap(if ((rec->rm_flags &XFS_RMAP_UNWRITTEN ) && !rb->allow_unwritten)return -EFSCORRUPTED ; - fsbno =xfs_agbno_to_fsb (cur->bc_ag.pag, rec->rm_startblock); + fsbno =xfs_agbno_to_fsb (to_perag (cur->bc_group), rec->rm_startblock);if (rec->rm_flags &XFS_RMAP_BMBT_BLOCK ) { rb->old_bmbt_block_count += rec->rm_blockcount;
fs/xfs/scrub/cow_repair.c +6 -3
@@ -145,7 +145,8 @@ xrep_cow_mark_shared_staging(xrep_cow_trim_refcount (xc, &rrec, rec);return xrep_cow_mark_file_range (xc, -xfs_agbno_to_fsb (cur->bc_ag.pag, rrec.rc_startblock), +xfs_agbno_to_fsb (to_perag (cur->bc_group), + rrec.rc_startblock), rrec.rc_blockcount); }
@@ -176,8 +177,9 @@ xrep_cow_mark_missing_staging(if (xc->next_bno >= rrec.rc_startblock) goto next; + error =xrep_cow_mark_file_range (xc, -xfs_agbno_to_fsb (cur->bc_ag.pag, xc->next_bno), +xfs_agbno_to_fsb (to_perag (cur->bc_group), xc->next_bno), rrec.rc_startblock - xc->next_bno);if (error)return error;
@@ -220,7 +222,8 @@ xrep_cow_mark_missing_staging_rmap( }return xrep_cow_mark_file_range (xc, -xfs_agbno_to_fsb (cur->bc_ag.pag, rec_bno), rec_len); +xfs_agbno_to_fsb (to_perag (cur->bc_group), rec_bno), + rec_len); }/*
fs/xfs/scrub/health.c +1 -1
@@ -276,7 +276,7 @@ xchk_ag_btree_del_cursor_if_sick( type_to_health_flag[sc->sm->sm_type].group == XHG_AG) mask &= ~sc->sick_mask; -if (xfs_ag_has_sickness ((*curp)->bc_ag.pag, mask)) { +if (xfs_group_has_sickness ((*curp)->bc_group, mask)) { sc->sm->sm_flags |=XFS_SCRUB_OFLAG_XFAIL ;xfs_btree_del_cursor (*curp,XFS_BTREE_NOERROR ); *curp =NULL ;
fs/xfs/scrub/ialloc.c +7 -7
@@ -258,7 +258,7 @@ xchk_iallocbt_chunk( {struct xfs_scrub *sc = bs->sc;struct xfs_mount *mp = bs->cur->bc_mp; -struct xfs_perag *pag = bs->cur->bc_ag.pag; +struct xfs_perag *pag =to_perag (bs->cur->bc_group);xfs_agblock_t agbno;xfs_extlen_t len;
@@ -318,7 +318,7 @@ xchk_iallocbt_check_cluster_ifree(* the record, compute which fs inode we're talking about. */ agino = irec->ir_startino + irec_ino; - fsino =xfs_agino_to_ino (bs->cur->bc_ag.pag, agino); + fsino =xfs_agino_to_ino (to_perag (bs->cur->bc_group), agino); irec_free = (irec->ir_free &XFS_INOBT_MASK (irec_ino)); if (be16_to_cpu(dip->di_magic) != XFS_DINODE_MAGIC ||
@@ -394,7 +394,7 @@ xchk_iallocbt_check_cluster(* ir_startino can be large enough to make im_boffset nonzero. */ ir_holemask = (irec->ir_holemask & cluster_mask); - imap.im_blkno =xfs_agbno_to_daddr (bs->cur->bc_ag.pag, agbno); + imap.im_blkno =xfs_agbno_to_daddr (to_perag (bs->cur->bc_group), agbno); imap.im_len =XFS_FSB_TO_BB (mp,M_IGEO (mp)->blocks_per_cluster); imap.im_boffset =XFS_INO_TO_OFFSET (mp, irec->ir_startino) << mp->m_sb.sb_inodelog;
@@ -405,9 +405,9 @@ xchk_iallocbt_check_cluster(return 0 ; } -trace_xchk_iallocbt_check_cluster (bs->cur->bc_ag.pag, irec->ir_startino, - imap.im_blkno, imap.im_len, cluster_base, nr_inodes, - cluster_mask, ir_holemask, +trace_xchk_iallocbt_check_cluster (to_perag (bs->cur->bc_group), + irec->ir_startino, imap.im_blkno, imap.im_len, + cluster_base, nr_inodes, cluster_mask, ir_holemask,XFS_INO_TO_OFFSET (mp, irec->ir_startino + cluster_base));
@@ -583,7 +583,7 @@ xchk_iallocbt_rec(uint16_t holemask;xfs_inobt_btrec_to_irec (mp, rec, &irec); -if (xfs_inobt_check_irec (bs->cur->bc_ag.pag, &irec) !=NULL ) { +if (xfs_inobt_check_irec (to_perag (bs->cur->bc_group), &irec) !=NULL ) {xchk_btree_set_corrupt (bs->sc, bs->cur,0 );return 0 ; }
fs/xfs/scrub/refcount.c +2 -1
@@ -453,7 +453,8 @@ xchk_refcountbt_rec(struct xchk_refcbt_records *rrc = bs->private;xfs_refcount_btrec_to_irec (rec, &irec); -if (xfs_refcount_check_irec (bs->cur->bc_ag.pag, &irec) !=NULL ) { +if (xfs_refcount_check_irec (to_perag (bs->cur->bc_group), &irec) != +NULL ) {xchk_btree_set_corrupt (bs->sc, bs->cur,0 );return 0 ; }
fs/xfs/scrub/rmap.c +1 -1
@@ -358,7 +358,7 @@ xchk_rmapbt_rec(struct xfs_rmap_irec irec;if (xfs_rmap_btrec_to_irec (rec, &irec) !=NULL || -xfs_rmap_check_irec (bs->cur->bc_ag.pag, &irec) !=NULL ) { +xfs_rmap_check_irec (to_perag (bs->cur->bc_group), &irec) !=NULL ) {xchk_btree_set_corrupt (bs->sc, bs->cur,0 );return 0 ; }
fs/xfs/scrub/rmap_repair.c +1 -1
@@ -622,7 +622,7 @@ xrep_rmap_walk_inobt(return error;xfs_inobt_btrec_to_irec (mp, rec, &irec); -if (xfs_inobt_check_irec (cur->bc_ag.pag, &irec) !=NULL ) +if (xfs_inobt_check_irec (to_perag (cur->bc_group), &irec) !=NULL )return -EFSCORRUPTED ; agino = irec.ir_startino;
fs/xfs/xfs_fsmap.c +4 -2
@@ -394,7 +394,8 @@ xfs_getfsmap_datadev_helper(struct xfs_getfsmap_info *info = priv;return xfs_getfsmap_helper (cur->bc_tp, info, rec, -xfs_agbno_to_daddr (cur->bc_ag.pag, rec->rm_startblock), +xfs_agbno_to_daddr (to_perag (cur->bc_group), + rec->rm_startblock),0 ); }
@@ -415,7 +416,8 @@ xfs_getfsmap_datadev_bnobt_helper( irec.rm_flags =0 ;return xfs_getfsmap_helper (cur->bc_tp, info, &irec, -xfs_agbno_to_daddr (cur->bc_ag.pag, rec->ar_startblock), +xfs_agbno_to_daddr (to_perag (cur->bc_group), + rec->ar_startblock),0 ); }
fs/xfs/xfs_health.c +6 -17
@@ -531,24 +531,13 @@ voidxfs_btree_mark_sick ( struct xfs_btree_cur *cur) { -switch (cur->bc_ops->type) { -case XFS_BTREE_TYPE_MEM : -/* no health state tracking for ephemeral btrees */ -return ; -case XFS_BTREE_TYPE_AG : +if (xfs_btree_is_bmap (cur->bc_ops)) { +xfs_bmap_mark_sick (cur->bc_ino.ip, cur->bc_ino.whichfork); +/* no health state tracking for ephemeral btrees */ + }else if (cur->bc_ops->type !=XFS_BTREE_TYPE_MEM ) { +ASSERT (cur->bc_group);ASSERT (cur->bc_ops->sick_mask); -xfs_ag_mark_sick (cur->bc_ag.pag, cur->bc_ops->sick_mask); -return ; -case XFS_BTREE_TYPE_INODE : -if (xfs_btree_is_bmap (cur->bc_ops)) { -xfs_bmap_mark_sick (cur->bc_ino.ip, - cur->bc_ino.whichfork); -return ; - } - fallthrough; -default : -ASSERT (0 ); -return ; +xfs_group_mark_sick (cur->bc_group, cur->bc_ops->sick_mask); } }
fs/xfs/xfs_trace.h +14 -14
@@ -2593,7 +2593,7 @@ TRACE_EVENT(xfs_btree_alloc_block, __entry->ino = cur->bc_ino.ip->i_ino;break ;case XFS_BTREE_TYPE_AG : - __entry->agno =pag_agno (cur->bc_ag.pag); + __entry->agno = cur->bc_group->xg_gno; __entry->ino =0 ;break ;case XFS_BTREE_TYPE_MEM :
@@ -2849,7 +2849,7 @@ DECLARE_EVENT_CLASS(xfs_rmap_class, ), TP_fast_assign( __entry->dev = cur->bc_mp->m_super->s_dev; - __entry->agno =pag_agno (cur->bc_ag.pag); + __entry->agno = cur->bc_group->xg_gno; __entry->agbno = agbno; __entry->len = len; __entry->owner = oinfo->oi_owner;
@@ -2894,7 +2894,7 @@ DECLARE_EVENT_CLASS(xfs_btree_error_class, __entry->ino = cur->bc_ino.ip->i_ino;break ;case XFS_BTREE_TYPE_AG : - __entry->agno =pag_agno (cur->bc_ag.pag); + __entry->agno = cur->bc_group->xg_gno; __entry->ino =0 ;break ;case XFS_BTREE_TYPE_MEM :
@@ -2948,7 +2948,7 @@ TRACE_EVENT(xfs_rmap_convert_state, __entry->ino = cur->bc_ino.ip->i_ino;break ;case XFS_BTREE_TYPE_AG : - __entry->agno =pag_agno (cur->bc_ag.pag); + __entry->agno = cur->bc_group->xg_gno; __entry->ino =0 ;break ;case XFS_BTREE_TYPE_MEM :
@@ -2983,7 +2983,7 @@ DECLARE_EVENT_CLASS(xfs_rmapbt_class, ), TP_fast_assign( __entry->dev = cur->bc_mp->m_super->s_dev; - __entry->agno =pag_agno (cur->bc_ag.pag); + __entry->agno = cur->bc_group->xg_gno; __entry->agbno = agbno; __entry->len = len; __entry->owner = owner;
@@ -3227,7 +3227,7 @@ DECLARE_EVENT_CLASS(xfs_refcount_class, ), TP_fast_assign( __entry->dev = cur->bc_mp->m_super->s_dev; - __entry->agno =pag_agno (cur->bc_ag.pag); + __entry->agno = cur->bc_group->xg_gno; __entry->agbno = agbno; __entry->len = len; ),
@@ -3258,7 +3258,7 @@ TRACE_EVENT(xfs_refcount_lookup, ), TP_fast_assign( __entry->dev = cur->bc_mp->m_super->s_dev; - __entry->agno =pag_agno (cur->bc_ag.pag); + __entry->agno = cur->bc_group->xg_gno; __entry->agbno = agbno; __entry->dir = dir; ),
@@ -3284,7 +3284,7 @@ DECLARE_EVENT_CLASS(xfs_refcount_extent_class, ), TP_fast_assign( __entry->dev = cur->bc_mp->m_super->s_dev; - __entry->agno =pag_agno (cur->bc_ag.pag); + __entry->agno = cur->bc_group->xg_gno; __entry->domain = irec->rc_domain; __entry->startblock = irec->rc_startblock; __entry->blockcount = irec->rc_blockcount;
@@ -3320,7 +3320,7 @@ DECLARE_EVENT_CLASS(xfs_refcount_extent_at_class, ), TP_fast_assign( __entry->dev = cur->bc_mp->m_super->s_dev; - __entry->agno =pag_agno (cur->bc_ag.pag); + __entry->agno = cur->bc_group->xg_gno; __entry->domain = irec->rc_domain; __entry->startblock = irec->rc_startblock; __entry->blockcount = irec->rc_blockcount;
@@ -3362,7 +3362,7 @@ DECLARE_EVENT_CLASS(xfs_refcount_double_extent_class, ), TP_fast_assign( __entry->dev = cur->bc_mp->m_super->s_dev; - __entry->agno =pag_agno (cur->bc_ag.pag); + __entry->agno = cur->bc_group->xg_gno; __entry->i1_domain = i1->rc_domain; __entry->i1_startblock = i1->rc_startblock; __entry->i1_blockcount = i1->rc_blockcount;
@@ -3412,7 +3412,7 @@ DECLARE_EVENT_CLASS(xfs_refcount_double_extent_at_class, ), TP_fast_assign( __entry->dev = cur->bc_mp->m_super->s_dev; - __entry->agno =pag_agno (cur->bc_ag.pag); + __entry->agno = cur->bc_group->xg_gno; __entry->i1_domain = i1->rc_domain; __entry->i1_startblock = i1->rc_startblock; __entry->i1_blockcount = i1->rc_blockcount;
@@ -3467,7 +3467,7 @@ DECLARE_EVENT_CLASS(xfs_refcount_triple_extent_class, ), TP_fast_assign( __entry->dev = cur->bc_mp->m_super->s_dev; - __entry->agno =pag_agno (cur->bc_ag.pag); + __entry->agno = cur->bc_group->xg_gno; __entry->i1_domain = i1->rc_domain; __entry->i1_startblock = i1->rc_startblock; __entry->i1_blockcount = i1->rc_blockcount;
@@ -4357,7 +4357,7 @@ TRACE_EVENT(xfs_btree_commit_afakeroot,TP_fast_assign ( __entry->dev = cur->bc_mp->m_super->s_dev;__assign_str (name); - __entry->agno =pag_agno (cur->bc_ag.pag); + __entry->agno = cur->bc_group->xg_gno; __entry->agbno = cur->bc_ag.afake->af_root; __entry->levels = cur->bc_ag.afake->af_levels; __entry->blocks = cur->bc_ag.afake->af_blocks;
@@ -4472,7 +4472,7 @@ TRACE_EVENT(xfs_btree_bload_block, __entry->agno =XFS_FSB_TO_AGNO (cur->bc_mp, fsb); __entry->agbno =XFS_FSB_TO_AGBNO (cur->bc_mp, fsb); }else { - __entry->agno =pag_agno (cur->bc_ag.pag); + __entry->agno = cur->bc_group->xg_gno; __entry->agbno =be32_to_cpu (ptr->s); } __entry->nr_records = nr_records;
PATCH 13/16 xfs: store a generic xfs_group pointer in xfs_getfsmap_info
In reply to Darrick J. WongFrom: Christoph Hellwig <[email protected]>
Replace the pag and rtg pointers with a generic group pointer.
--- fs/xfs/xfs_fsmap.c | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-)
fs/xfs/xfs_fsmap.c +14 -12
@@ -158,7 +158,7 @@ struct xfs_getfsmap_info {struct xfs_fsmap_head *head;struct fsmap *fsmap_recs;/* mapping records */ struct xfs_buf *agf_bp;/* AGF, for refcount queries */ -struct xfs_perag *pag;/* AG info, if applicable */ +struct xfs_group *group;/* group info, if applicable */ xfs_daddr_t next_daddr;/* next daddr we expect */ /* daddr of low fsmap key when we're using the rtbitmap */ xfs_daddr_t low_daddr;
@@ -216,12 +216,13 @@ xfs_getfsmap_is_shared(if (!xfs_has_reflink (mp))return 0 ;/* rt files will have no perag structure */ -if (!info->pag) +if (!info->group)return 0 ;/* Are there any shared blocks here? */ flen =0 ; - cur =xfs_refcountbt_init_cursor (mp, tp, info->agf_bp, info->pag); + cur =xfs_refcountbt_init_cursor (mp, tp, info->agf_bp, +to_perag (info->group)); error =xfs_refcount_find_shared (cur, rec->rm_startblock, rec->rm_blockcount, &fbno, &flen, false);
@@ -353,7 +354,8 @@ xfs_getfsmap_helper(return -ECANCELED ;trace_xfs_fsmap_mapping (mp, info->dev, - info->pag ?pag_agno (info->pag) :NULLAGNUMBER , rec); + info->group ? info->group->xg_gno :NULLAGNUMBER , + rec); fmr.fmr_device = info->dev; fmr.fmr_physical = rec_daddr;
@@ -519,7 +521,7 @@ __xfs_getfsmap_datadev(* Set the AG high key from the fsmap high key if this * is the last AG that we're querying. */ - info->pag = pag; + info->group =pag_group (pag);if (pag_agno (pag) == end_ag) { info->high.rm_startblock =XFS_FSB_TO_AGBNO (mp, end_fsb);
@@ -569,7 +571,7 @@ __xfs_getfsmap_datadev(if (error)break ; } - info->pag =NULL ; + info->group =NULL ; }if (bt_cur)
@@ -579,9 +581,9 @@ __xfs_getfsmap_datadev(xfs_trans_brelse (tp, info->agf_bp); info->agf_bp =NULL ; } -if (info->pag) { -xfs_perag_rele (info->pag); - info->pag =NULL ; +if (info->group) { +xfs_perag_rele (pag); + info->group =NULL ; }else if (pag) {/* loop termination case */ xfs_perag_rele (pag);
@@ -604,7 +606,7 @@ xfs_getfsmap_datadev_rmapbt_query(/* Allocate cursor for this AG and query_range it. */ *curpp =xfs_rmapbt_init_cursor (tp->t_mountp, tp, info->agf_bp, - info->pag); +to_perag (info->group));return xfs_rmap_query_range (*curpp, &info->low, &info->high, xfs_getfsmap_datadev_helper, info); }
@@ -637,7 +639,7 @@ xfs_getfsmap_datadev_bnobt_query(/* Allocate cursor for this AG and query_range it. */ *curpp =xfs_bnobt_init_cursor (tp->t_mountp, tp, info->agf_bp, - info->pag); +to_perag (info->group)); key->ar_startblock = info->low.rm_startblock; key[1 ].ar_startblock = info->high.rm_startblock; return xfs_alloc_query_range(*curpp, key, &key[1],
@@ -997,7 +999,7 @@ xfs_getfsmap( info.dev = handlers[i].dev; info.last = false; - info.pag =NULL ; + info.group =NULL ; info.low_daddr =XFS_BUF_DADDR_NULL ; info.low.rm_blockcount =0 ; error = handlers[i].fn (tp, dkeys, &info);
PATCH 14/16 xfs: add group based bno conversion helpers
In reply to Darrick J. WongFrom: Christoph Hellwig <[email protected]>
Add/move the blocks, blklog and blkmask fields to the generic groups structure so that code can work with AGs and RTGs by just using the right index into the array.
Then, add convenience helpers to convert block numbers based on the generic group. This will allow writing code that doesn't care if it is used on AGs or the upcoming realtime groups.
--- fs/xfs/libxfs/xfs_group.c | 9 +++++++ fs/xfs/libxfs/xfs_group.h | 56 +++++++++++++++++++++++++++++++++++++++++++++ fs/xfs/libxfs/xfs_sb.c | 7 ++++++ fs/xfs/xfs_mount.h | 30 ++++++++++++++++++++++++ 4 files changed, 102 insertions(+)
fs/xfs/libxfs/xfs_group.c +9 -0
@@ -214,3 +214,12 @@ xfs_group_insert(#endif return error; } + +struct xfs_group * +xfs_group_get_by_fsb ( +struct xfs_mount *mp, +xfs_fsblock_t fsbno, +enum xfs_group_type type) +{ +return xfs_group_get (mp,xfs_fsb_to_gno (mp, fsbno, type), type); +}
fs/xfs/libxfs/xfs_group.h +56 -0
66 lines not on this page · raw message
fs/xfs/libxfs/xfs_sb.c +7 -0
@@ -988,6 +988,8 @@ xfs_sb_mount_common(struct xfs_mount *mp, struct xfs_sb *sbp) { + struct xfs_groups *ags = &mp->m_groups[XG_TYPE_AG]; + mp->m_agfrotor =0 ;atomic_set (&mp->m_agirotor,0 ); mp->m_maxagi = mp->m_sb.sb_agcount;
@@ -998,6 +1000,11 @@ xfs_sb_mount_common( mp->m_blockmask = sbp->sb_blocksize -1 ; mp->m_blockwsize = sbp->sb_blocksize >>XFS_WORDLOG ; mp->m_blockwmask = mp->m_blockwsize -1 ; + + ags->blocks = mp->m_sb.sb_agblocks; + ags->blklog = mp->m_sb.sb_agblklog; + ags->blkmask =xfs_mask32lo (mp->m_sb.sb_agblklog); +xfs_mount_sb_set_rextsize (mp, sbp); mp->m_alloc_mxr[0 ] =xfs_allocbt_maxrecs (mp, sbp->sb_blocksize, true);
fs/xfs/xfs_mount.h +30 -0
@@ -71,8 +71,38 @@ struct xfs_inodegc {unsigned int cpu; }; +/* +* Container for each type of groups, used to look up individual groups and +* describes the geometry. +*/ struct xfs_groups {struct xarray xa; + +/* +* Maximum capacity of the group in FSBs. +* +* Each group is laid out densely in the daddr space. For the +* degenerate case of a pre-rtgroups filesystem, the incore rtgroup +* pretends to have a zero-block and zero-blklog rtgroup. +*/ +uint32_t blocks; + +/* +* Log(2) of the logical size of each group. +* +* Compared to the blocks field above this is rounded up to the next +* power of two, and thus lays out the xfs_fsblock_t/xfs_rtblock_t +* space sparsely with a hole from blocks to (1 << blklog) at the end +* of each group. +*/ +uint8_t blklog; + +/* +* Mask to extract the group-relative block number from a FSB. +* For a pre-rtgroups filesystem we pretend to have one very large +* rtgroup, so this mask must be 64-bit. +*/ +uint64_t blkmask; };/*
PATCH 15/16 xfs: remove xfs_group_intent_hold and xfs_group_intent_rele
In reply to Darrick J. WongFrom: Christoph Hellwig <[email protected]>
Each of them just has a single caller, so fold them.
--- fs/xfs/xfs_drain.c | 36 +++++++++--------------------------- 1 file changed, 9 insertions(+), 27 deletions(-)
fs/xfs/xfs_drain.c +9 -27
@@ -94,31 +94,11 @@ static inline int xfs_defer_drain_wait(struct xfs_defer_drain *dr) }/* -* Declare an intent to update group metadata. Other threads that need -* exclusive access can decide to back off if they see declared intentions. -*/ -static void -xfs_group_intent_hold ( -struct xfs_group *xg) -{ -trace_xfs_group_intent_hold (xg, __return_address); -xfs_defer_drain_grab (&xg->xg_intents_drain); -} - -/* -* Release our intent to update this groups metadata. -*/ -static void -xfs_group_intent_rele ( -struct xfs_group *xg) -{ -trace_xfs_group_intent_rele (xg, __return_address); -xfs_defer_drain_rele (&xg->xg_intents_drain); -} - -/* -* Get a passive reference to the AG that contains a fsbno and declare an intent -* to update its metadata. +* Get a passive reference to the AG that contains a fsbno and declare an +* intent to update its metadata. +* +* Other threads that need exclusive access can decide to back off if they see +* declared intentions. */ struct xfs_perag * xfs_perag_intent_get(
@@ -131,7 +111,8 @@ xfs_perag_intent_get(if (!pag)return NULL ; -xfs_group_intent_hold (pag_group (pag)); +trace_xfs_group_intent_hold (pag_group (pag), __return_address); +xfs_defer_drain_grab (pag_group (pag).xg_intents_drain);return pag; }
@@ -143,7 +124,8 @@ voidxfs_perag_intent_put ( struct xfs_perag *pag) { -xfs_group_intent_rele (pag_group (pag)); +trace_xfs_group_intent_rele (pag_group(pag ), __return_address); +xfs_defer_drain_rele (pag_group (pag).xg_intents_drain);xfs_perag_put (pag); }
PATCH 16/16 xfs: store a generic group structure in the intents
In reply to Darrick J. WongFrom: Christoph Hellwig <[email protected]>
Replace the pag pointers in the extent free, bmap, rmap and refcount intent structures with a pointer to the generic group to prepare for adding intents for realtime groups.
--- fs/xfs/libxfs/xfs_alloc.h | 2 +- fs/xfs/libxfs/xfs_bmap.h | 2 +- fs/xfs/libxfs/xfs_refcount.c | 9 +++++---- fs/xfs/libxfs/xfs_refcount.h | 2 +- fs/xfs/libxfs/xfs_rmap.c | 16 +++++++++------- fs/xfs/libxfs/xfs_rmap.h | 2 +- fs/xfs/xfs_bmap_item.c | 5 +++-- fs/xfs/xfs_drain.c | 36 ++++++++++++++++++------------------ fs/xfs/xfs_drain.h | 12 ++++++------ fs/xfs/xfs_extfree_item.c | 14 ++++++++------ fs/xfs/xfs_refcount_item.c | 9 +++++---- fs/xfs/xfs_rmap_item.c | 9 +++++---- 12 files changed, 63 insertions(+), 55 deletions(-)
fs/xfs/libxfs/xfs_alloc.h +1 -1
@@ -248,7 +248,7 @@ struct xfs_extent_free_item {uint64_t xefi_owner;xfs_fsblock_t xefi_startblock;/* starting fs block number */ xfs_extlen_t xefi_blockcount;/* number of blocks in extent */ -struct xfs_perag *xefi_pag; +struct xfs_group *xefi_group;unsigned int xefi_flags;enum xfs_ag_resv_type xefi_agresv; };
fs/xfs/libxfs/xfs_bmap.h +1 -1
@@ -248,7 +248,7 @@ struct xfs_bmap_intent {enum xfs_bmap_intent_type bi_type;int bi_whichfork;struct xfs_inode *bi_owner; -struct xfs_perag *bi_pag; +struct xfs_group *bi_group;struct xfs_bmbt_irec bi_bmap; };
fs/xfs/libxfs/xfs_refcount.c +5 -4
@@ -1358,7 +1358,7 @@ xfs_refcount_finish_one(* If we haven't gotten a cursor or the cursor AG doesn't match * the startblock, get one now. */ -if (rcur !=NULL &&to_perag (rcur->bc_group) != ri->ri_pag) { +if (rcur !=NULL && rcur->bc_group != ri->ri_group) { nr_ops = rcur->bc_refc.nr_ops; shape_changes = rcur->bc_refc.shape_changes;xfs_btree_del_cursor (rcur,0 );
@@ -1366,13 +1366,14 @@ xfs_refcount_finish_one( *pcur =NULL ; }if (rcur ==NULL ) { - error =xfs_alloc_read_agf (ri->ri_pag, tp, +struct xfs_perag *pag =to_perag (ri->ri_group); + + error =xfs_alloc_read_agf (pag, tp,XFS_ALLOC_FLAG_FREEING , &agbp);if (error)return error; - *pcur = rcur =xfs_refcountbt_init_cursor (mp, tp, agbp, - ri->ri_pag); + *pcur = rcur =xfs_refcountbt_init_cursor (mp, tp, agbp, pag); rcur->bc_refc.nr_ops = nr_ops; rcur->bc_refc.shape_changes = shape_changes; }
fs/xfs/libxfs/xfs_refcount.h +1 -1
@@ -56,7 +56,7 @@ enum xfs_refcount_intent_type {struct xfs_refcount_intent {struct list_head ri_list; -struct xfs_perag *ri_pag; +struct xfs_group *ri_group;enum xfs_refcount_intent_type ri_type;xfs_extlen_t ri_blockcount;xfs_fsblock_t ri_startblock;
fs/xfs/libxfs/xfs_rmap.c +9 -7
@@ -2586,28 +2586,30 @@ xfs_rmap_finish_one(* If we haven't gotten a cursor or the cursor AG doesn't match * the startblock, get one now. */ -if (rcur !=NULL &&to_perag (rcur->bc_group) != ri->ri_pag) { +if (rcur !=NULL && rcur->bc_group != ri->ri_group) {xfs_btree_del_cursor (rcur,0 ); rcur =NULL ; *pcur =NULL ; }if (rcur ==NULL ) { +struct xfs_perag *pag =to_perag (ri->ri_group); +/* * Refresh the freelist before we start changing the * rmapbt, because a shape change could cause us to * allocate blocks. */ - error =xfs_free_extent_fix_freelist (tp, ri->ri_pag, &agbp); + error =xfs_free_extent_fix_freelist (tp, pag, &agbp);if (error) { -xfs_ag_mark_sick (ri->ri_pag,XFS_SICK_AG_AGFL ); +xfs_ag_mark_sick (pag,XFS_SICK_AG_AGFL );return error; }if (XFS_IS_CORRUPT (tp->t_mountp, !agbp)) { -xfs_ag_mark_sick (ri->ri_pag,XFS_SICK_AG_AGFL ); +xfs_ag_mark_sick (pag,XFS_SICK_AG_AGFL );return -EFSCORRUPTED ; } - *pcur = rcur =xfs_rmapbt_init_cursor (mp, tp, agbp, ri->ri_pag); + *pcur = rcur =xfs_rmapbt_init_cursor (mp, tp, agbp, pag); } xfs_rmap_ino_owner(&oinfo, ri->ri_owner, ri->ri_whichfork,
@@ -2620,8 +2622,8 @@ xfs_rmap_finish_one(if (error)return error; -xfs_rmap_update_hook (tp,pag_group (ri->ri_pag), ri->ri_type, bno, - ri->ri_bmap.br_blockcount, unwritten, &oinfo); +xfs_rmap_update_hook (tp, ri->ri_group, ri->ri_type, bno, + ri->ri_bmap.br_blockcount, unwritten, &oinfo);return 0 ; }
fs/xfs/libxfs/xfs_rmap.h +1 -1
@@ -173,7 +173,7 @@ struct xfs_rmap_intent {int ri_whichfork;uint64_t ri_owner;struct xfs_bmbt_irec ri_bmap; -struct xfs_perag *ri_pag; +struct xfs_group *ri_group; };/* functions for updating the rmapbt based on bmbt map/unmap operations */
fs/xfs/xfs_bmap_item.c +3 -2
@@ -334,7 +334,8 @@ xfs_bmap_update_get_group(* intent drops the intent count, ensuring that the intent count * remains nonzero across the transaction roll. */ - bi->bi_pag =xfs_perag_intent_get (mp, bi->bi_bmap.br_startblock); + bi->bi_group =xfs_group_intent_get (mp, bi->bi_bmap.br_startblock, +XG_TYPE_AG ); }/* Add this deferred BUI to the transaction. */
@@ -368,7 +369,7 @@ xfs_bmap_update_put_group(if (xfs_ifork_is_realtime (bi->bi_owner, bi->bi_whichfork))return ; -xfs_perag_intent_put (bi->bi_pag); +xfs_group_intent_put (bi->bi_group); }/* Cancel a deferred bmap update. */
fs/xfs/xfs_drain.c +18 -18
@@ -94,39 +94,39 @@ static inline int xfs_defer_drain_wait(struct xfs_defer_drain *dr) }/* -* Get a passive reference to the AG that contains a fsbno and declare an +* Get a passive reference to the group that contains a fsbno and declare an * intent to update its metadata. * * Other threads that need exclusive access can decide to back off if they see * declared intentions. */ -struct xfs_perag * -xfs_perag_intent_get ( +struct xfs_group * +xfs_group_intent_get (struct xfs_mount *mp, -xfs_fsblock_t fsbno) +xfs_fsblock_t fsbno, +enum xfs_group_type type) { -struct xfs_perag *pag; +struct xfs_group *xg; - pag =xfs_perag_get (mp,XFS_FSB_TO_AGNO (mp, fsbno)); -if (!pag) + xg =xfs_group_get_by_fsb (mp, fsbno, type); +if (!xg)return NULL ; - -trace_xfs_group_intent_hold (pag_group (pag), __return_address); -xfs_defer_drain_grab (pag_group (pag).xg_intents_drain); -return pag; +trace_xfs_group_intent_hold (xg, __return_address); +xfs_defer_drain_grab (&xg->xg_intents_drain); +return xg; }/* -* Release our intent to update this AG's metadata, and then release our -* passive ref to the AG. +* Release our intent to update this groups metadata, and then release our +* passive ref to it. */ void -xfs_perag_intent_put ( -struct xfs_perag *pag) +xfs_group_intent_put ( +struct xfs_group *xg) { -trace_xfs_group_intent_rele (pag_group (pag), __return_address); -xfs_defer_drain_rele (pag_group (pag).xg_intents_drain); -xfs_perag_put (pag); +trace_xfs_group_intent_rele (xg, __return_address); +xfs_defer_drain_rele (&xg->xg_intents_drain); +xfs_group_put (xg); }/*
fs/xfs/xfs_drain.h +6 -6
@@ -62,9 +62,9 @@ void xfs_drain_wait_enable(void);* soon as the item is added to the transaction and cannot drop the counter * until the item is finished or cancelled. */ -struct xfs_perag *xfs_perag_intent_get (struct xfs_mount *mp, -xfs_fsblock_t fsbno); -void xfs_perag_intent_put (struct xfs_perag *pag); +struct xfs_group *xfs_group_intent_get (struct xfs_mount *mp, +xfs_fsblock_t fsbno,enum xfs_group_type type); +void xfs_group_intent_put (struct xfs_group *rtg);int xfs_group_intent_drain (struct xfs_group *xg);bool xfs_group_intent_busy (struct xfs_group *xg);
@@ -75,9 +75,9 @@ struct xfs_defer_drain { /* empty */ };#define xfs_defer_drain_free (dr) ((void)0)#define xfs_defer_drain_init (dr) ((void)0) -#define xfs_perag_intent_get (mp, fsbno) \ - xfs_perag_get((mp), XFS_FSB_TO_AGNO(mp, fsbno)) -#define xfs_perag_intent_put (pag) xfs_perag_put(pag) +#define xfs_group_intent_get (_mp, _fsbno, _type) \ + xfs_group_get_by_fsb((_mp), (_fsbno), (_type)) +#define xfs_group_intent_put (xg) xfs_group_put(xg)#endif /* CONFIG_XFS_DRAIN_INTENTS */
fs/xfs/xfs_extfree_item.c +8 -6
@@ -362,7 +362,7 @@ xfs_extent_free_diff_items(struct xfs_extent_free_item *ra =xefi_entry (a);struct xfs_extent_free_item *rb =xefi_entry (b); -return pag_agno (ra->xefi_pag) -pag_agno (rb->xefi_pag); +return ra->xefi_group->xg_gno - rb->xefi_group->xg_gno; }/* Log a free extent to the intent item. */
@@ -447,7 +447,8 @@ xfs_extent_free_defer_add(trace_xfs_extent_free_defer (mp, xefi); - xefi->xefi_pag =xfs_perag_intent_get (mp, xefi->xefi_startblock); + xefi->xefi_group =xfs_group_intent_get (mp, xefi->xefi_startblock, +XG_TYPE_AG );if (xefi->xefi_agresv ==XFS_AG_RESV_AGFL ) *dfpp =xfs_defer_add (tp, &xefi->xefi_list, &xfs_agfl_free_defer_type);
@@ -463,7 +464,7 @@ xfs_extent_free_cancel_item( {struct xfs_extent_free_item *xefi =xefi_entry (item); -xfs_perag_intent_put (xefi->xefi_pag); +xfs_group_intent_put (xefi->xefi_group);kmem_cache_free (xfs_extfree_item_cache, xefi); }
@@ -499,7 +500,7 @@ xfs_extent_free_finish_item(* in this EFI to the EFD so this works correctly. */ if (!(xefi->xefi_flags &XFS_EFI_CANCELLED )) - error =__xfs_free_extent (tp, xefi->xefi_pag, agbno, + error =__xfs_free_extent (tp,to_perag (xefi->xefi_group), agbno, xefi->xefi_blockcount, &oinfo, xefi->xefi_agresv, xefi->xefi_flags &XFS_EFI_SKIP_DISCARD );if (error == -EAGAIN ) {
@@ -545,7 +546,7 @@ xfs_agfl_free_finish_item(trace_xfs_agfl_free_deferred (mp, xefi); - error =xfs_alloc_read_agf (xefi->xefi_pag, tp,0 , &agbp); + error =xfs_alloc_read_agf (to_perag (xefi->xefi_group), tp,0 , &agbp);if (!error) error =xfs_free_ag_extent (tp, agbp, agbno,1 , &oinfo,XFS_AG_RESV_AGFL );
@@ -578,7 +579,8 @@ xfs_efi_recover_work( xefi->xefi_blockcount = extp->ext_len; xefi->xefi_agresv =XFS_AG_RESV_NONE ; xefi->xefi_owner =XFS_RMAP_OWN_UNKNOWN ; - xefi->xefi_pag =xfs_perag_intent_get (mp, extp->ext_start); + xefi->xefi_group =xfs_group_intent_get (mp, extp->ext_start, +XG_TYPE_AG );xfs_defer_add_item (dfp, &xefi->xefi_list); }
fs/xfs/xfs_refcount_item.c +5 -4
@@ -244,7 +244,7 @@ xfs_refcount_update_diff_items(struct xfs_refcount_intent *ra =ci_entry (a);struct xfs_refcount_intent *rb =ci_entry (b); -return pag_agno (ra->ri_pag) -pag_agno (rb->ri_pag); +return ra->ri_group->xg_gno - rb->ri_group->xg_gno; }/* Log refcount updates in the intent item. */
@@ -330,7 +330,7 @@ xfs_refcount_defer_add(trace_xfs_refcount_defer (mp, ri); - ri->ri_pag =xfs_perag_intent_get (mp, ri->ri_startblock); + ri->ri_group =xfs_group_intent_get (mp, ri->ri_startblock,XG_TYPE_AG );xfs_defer_add (tp, &ri->ri_list, &xfs_refcount_update_defer_type); }
@@ -341,7 +341,7 @@ xfs_refcount_update_cancel_item( {struct xfs_refcount_intent *ri =ci_entry (item); -xfs_perag_intent_put (ri->ri_pag); +xfs_group_intent_put (ri->ri_group);kmem_cache_free (xfs_refcount_intent_cache, ri); }
@@ -431,7 +431,8 @@ xfs_cui_recover_work( ri->ri_type = pmap->pe_flags &XFS_REFCOUNT_EXTENT_TYPE_MASK ; ri->ri_startblock = pmap->pe_startblock; ri->ri_blockcount = pmap->pe_len; - ri->ri_pag =xfs_perag_intent_get (mp, pmap->pe_startblock); + ri->ri_group =xfs_group_intent_get (mp, pmap->pe_startblock, +XG_TYPE_AG );xfs_defer_add_item (dfp, &ri->ri_list); }
fs/xfs/xfs_rmap_item.c +5 -4
@@ -243,7 +243,7 @@ xfs_rmap_update_diff_items(struct xfs_rmap_intent *ra =ri_entry (a);struct xfs_rmap_intent *rb =ri_entry (b); -return pag_agno (ra->ri_pag) -pag_agno (rb->ri_pag); +return ra->ri_group->xg_gno - rb->ri_group->xg_gno; }/* Log rmap updates in the intent item. */
@@ -353,7 +353,8 @@ xfs_rmap_defer_add(trace_xfs_rmap_defer (mp, ri); - ri->ri_pag =xfs_perag_intent_get (mp, ri->ri_bmap.br_startblock); + ri->ri_group =xfs_group_intent_get (mp, ri->ri_bmap.br_startblock, +XG_TYPE_AG );xfs_defer_add (tp, &ri->ri_list, &xfs_rmap_update_defer_type); }
@@ -364,7 +365,7 @@ xfs_rmap_update_cancel_item( {struct xfs_rmap_intent *ri =ri_entry (item); -xfs_perag_intent_put (ri->ri_pag); +xfs_group_intent_put (ri->ri_group);kmem_cache_free (xfs_rmap_intent_cache, ri); }
@@ -494,7 +495,7 @@ xfs_rui_recover_work( ri->ri_bmap.br_blockcount = map->me_len; ri->ri_bmap.br_state = (map->me_flags &XFS_RMAP_EXTENT_UNWRITTEN ) ?XFS_EXT_UNWRITTEN :XFS_EXT_NORM ; - ri->ri_pag =xfs_perag_intent_get (mp, map->me_startblock); + ri->ri_group =xfs_group_intent_get (mp, map->me_startblock,XG_TYPE_AG );xfs_defer_add_item (dfp, &ri->ri_list); }
PATCH 3/9 xfs: metadata inode directory trees
In reply to Darrick J. WongHi all,
This series delivers a new feature -- metadata inode directories. This is a separate directory tree (rooted in the superblock) that contains only inodes that contain filesystem metadata. Different metadata objects can be looked up with regular paths.
Start by creating xfs_imeta{dir,file}* functions to mediate access to the metadata directory tree. By the end of this mega series, all existing metadata inodes (rt+quota) will use this directory tree instead of the superblock.
Next, define the metadir on-disk format, which consists of marking inodes with a new iflag that says they're metadata. This prevents bulkstat and friends from ever getting their hands on fs metadata files.
If you're going to start using this code, I strongly recommend pulling from my git trees, which are linked below.
This has been running on the djcloud for months with no problems. Enjoy! Comments and questions are, as always, welcome.
--D
kernel git tree:
https://git.kernel.org/cgit/linux/kernel/git/djwong/xfs-linux.git/log/?h=metadata-directory-tree
xfsprogs git tree:
https://git.kernel.org/cgit/linux/kernel/git/djwong/xfsprogs-dev.git/log/?h=metadata-directory-tree
---
Commits in this patchset:
* xfs: constify the xfs_sb predicates
* xfs: constify the xfs_inode predicates
* xfs: rename metadata inode predicates
* xfs: standardize EXPERIMENTAL warning generation
* xfs: define the on-disk format for the metadir feature
* xfs: iget for metadata inodes
* xfs: load metadata directory root at mount time
* xfs: enforce metadata inode flag
* xfs: read and write metadata inode directory tree
* xfs: disable the agi rotor for metadata inodes
* xfs: hide metadata inodes from everyone because they are special
* xfs: advertise metadata directory feature
* xfs: allow bulkstat to return metadata directories
* xfs: don't count metadata directory files to quota
* xfs: mark quota inodes as metadata files
* xfs: adjust xfs_bmap_add_attrfork for metadir
* xfs: record health problems with the metadata directory
* xfs: refactor directory tree root predicates
* xfs: do not count metadata directory files when doing online quotacheck
* xfs: don't fail repairs on metadata files with no attr fork
* xfs: metadata files can have xattrs if metadir is enabled
* xfs: adjust parent pointer scrubber for sb-rooted metadata files
* xfs: fix di_metatype field of inodes that won't load
* xfs: scrub metadata directories
* xfs: check the metadata directory inumber in superblocks
* xfs: move repair temporary files to the metadata directory tree
* xfs: check metadata directory file path connectivity
* xfs: confirm dotdot target before replacing it during a repair
* xfs: repair metadata directory file path connectivity
--- fs/xfs/Makefile | 5 fs/xfs/libxfs/xfs_attr.c | 5 fs/xfs/libxfs/xfs_bmap.c | 5 fs/xfs/libxfs/xfs_format.h | 121 +++++++-- fs/xfs/libxfs/xfs_fs.h | 25 ++ fs/xfs/libxfs/xfs_health.h | 6 fs/xfs/libxfs/xfs_ialloc.c | 58 +++- fs/xfs/libxfs/xfs_inode_buf.c | 90 ++++++- fs/xfs/libxfs/xfs_inode_buf.h | 3 fs/xfs/libxfs/xfs_inode_util.c | 2 fs/xfs/libxfs/xfs_log_format.h | 2 fs/xfs/libxfs/xfs_metadir.c | 481 ++++++++++++++++++++++++++++++++++++ fs/xfs/libxfs/xfs_metadir.h | 47 ++++ fs/xfs/libxfs/xfs_metafile.c | 52 ++++ fs/xfs/libxfs/xfs_metafile.h | 31 ++ fs/xfs/libxfs/xfs_ondisk.h | 2 fs/xfs/libxfs/xfs_sb.c | 12 + fs/xfs/libxfs/xfs_types.c | 4 fs/xfs/libxfs/xfs_types.h | 2 fs/xfs/scrub/agheader.c | 5 fs/xfs/scrub/common.c | 65 ++++- fs/xfs/scrub/common.h | 5 fs/xfs/scrub/dir.c | 10 + fs/xfs/scrub/dir_repair.c | 20 + fs/xfs/scrub/dirtree.c | 32 ++ fs/xfs/scrub/dirtree.h | 12 - fs/xfs/scrub/findparent.c | 28 ++ fs/xfs/scrub/health.c | 1 fs/xfs/scrub/inode.c | 35 ++- fs/xfs/scrub/inode_repair.c | 34 ++- fs/xfs/scrub/metapath.c | 521 +++++++++++++++++++++++++++++++++++++++ fs/xfs/scrub/nlinks.c | 4 fs/xfs/scrub/nlinks_repair.c | 4 fs/xfs/scrub/orphanage.c | 4 fs/xfs/scrub/parent.c | 39 ++- fs/xfs/scrub/parent_repair.c | 37 ++- fs/xfs/scrub/quotacheck.c | 7 - fs/xfs/scrub/refcount_repair.c | 2 fs/xfs/scrub/repair.c | 22 +- fs/xfs/scrub/repair.h | 3 fs/xfs/scrub/scrub.c | 12 + fs/xfs/scrub/scrub.h | 2 fs/xfs/scrub/stats.c | 1 fs/xfs/scrub/tempfile.c | 105 ++++++++ fs/xfs/scrub/tempfile.h | 3 fs/xfs/scrub/trace.c | 1 fs/xfs/scrub/trace.h | 42 +++ fs/xfs/xfs_dquot.c | 1 fs/xfs/xfs_fsops.c | 4 fs/xfs/xfs_health.c | 2 fs/xfs/xfs_icache.c | 74 ++++++ fs/xfs/xfs_inode.c | 19 + fs/xfs/xfs_inode.h | 36 ++- fs/xfs/xfs_inode_item.c | 7 - fs/xfs/xfs_inode_item_recover.c | 2 fs/xfs/xfs_ioctl.c | 7 + fs/xfs/xfs_iops.c | 15 + fs/xfs/xfs_itable.c | 33 ++ fs/xfs/xfs_itable.h | 3 fs/xfs/xfs_message.c | 47 ++++ fs/xfs/xfs_message.h | 19 + fs/xfs/xfs_mount.c | 31 ++ fs/xfs/xfs_mount.h | 11 + fs/xfs/xfs_qm.c | 36 +++ fs/xfs/xfs_quota.h | 5 fs/xfs/xfs_rtalloc.c | 38 ++- fs/xfs/xfs_super.c | 13 - fs/xfs/xfs_trace.c | 2 fs/xfs/xfs_trace.h | 102 ++++++++ fs/xfs/xfs_trans_dquot.c | 6 fs/xfs/xfs_xattr.c | 3 71 files changed, 2324 insertions(+), 201 deletions(-) create mode 100644 fs/xfs/libxfs/xfs_metadir.c create mode 100644 fs/xfs/libxfs/xfs_metadir.h create mode 100644 fs/xfs/libxfs/xfs_metafile.c create mode 100644 fs/xfs/libxfs/xfs_metafile.h create mode 100644 fs/xfs/scrub/metapath.c
PATCH 1/29 xfs: constify the xfs_sb predicates
From: Darrick J. Wong <[email protected]>
Change the xfs_sb predicates to take a const struct xfs_sb pointer because they do not change the superblock.
--- fs/xfs/libxfs/xfs_format.h | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-)
fs/xfs/libxfs/xfs_format.h +12 -12
@@ -278,7 +278,7 @@ struct xfs_dsb {#define XFS_SB_VERSION_NUM (sbp) ((sbp)->sb_versionnum & XFS_SB_VERSION_NUMBITS) -static inline bool xfs_sb_is_v5 (struct xfs_sb *sbp) +static inline bool xfs_sb_is_v5 (const struct xfs_sb *sbp) {return XFS_SB_VERSION_NUM (sbp) ==XFS_SB_VERSION_5 ; }
@@ -287,12 +287,12 @@ static inline bool xfs_sb_is_v5(struct xfs_sb *sbp)* Detect a mismatched features2 field. Older kernels read/wrote * this into the wrong slot, so to be safe we keep them in sync. */ -static inline bool xfs_sb_has_mismatched_features2 (struct xfs_sb *sbp) +static inline bool xfs_sb_has_mismatched_features2 (const struct xfs_sb *sbp) {return sbp->sb_bad_features2 != sbp->sb_features2; } -static inline bool xfs_sb_version_hasmorebits (struct xfs_sb *sbp) +static inline bool xfs_sb_version_hasmorebits (const struct xfs_sb *sbp) {return xfs_sb_is_v5 (sbp) || (sbp->sb_versionnum &XFS_SB_VERSION_MOREBITSBIT );
@@ -342,8 +342,8 @@ static inline void xfs_sb_version_addprojid32(struct xfs_sb *sbp)#define XFS_SB_FEAT_COMPAT_UNKNOWN ~XFS_SB_FEAT_COMPAT_ALLstatic inline bool xfs_sb_has_compat_feature ( -struct xfs_sb *sbp, -uint32_t feature) +const struct xfs_sb *sbp, +uint32_t feature) {return (sbp->sb_features_compat & feature) !=0 ; }
@@ -360,8 +360,8 @@ xfs_sb_has_compat_feature(#define XFS_SB_FEAT_RO_COMPAT_UNKNOWN ~XFS_SB_FEAT_RO_COMPAT_ALLstatic inline bool xfs_sb_has_ro_compat_feature ( -struct xfs_sb *sbp, -uint32_t feature) +const struct xfs_sb *sbp, +uint32_t feature) {return (sbp->sb_features_ro_compat & feature) !=0 ; }
@@ -387,8 +387,8 @@ xfs_sb_has_ro_compat_feature(#define XFS_SB_FEAT_INCOMPAT_UNKNOWN ~XFS_SB_FEAT_INCOMPAT_ALLstatic inline bool xfs_sb_has_incompat_feature ( -struct xfs_sb *sbp, -uint32_t feature) +const struct xfs_sb *sbp, +uint32_t feature) {return (sbp->sb_features_incompat & feature) !=0 ; }
@@ -399,8 +399,8 @@ xfs_sb_has_incompat_feature(#define XFS_SB_FEAT_INCOMPAT_LOG_UNKNOWN ~XFS_SB_FEAT_INCOMPAT_LOG_ALLstatic inline bool xfs_sb_has_incompat_log_feature ( -struct xfs_sb *sbp, -uint32_t feature) +const struct xfs_sb *sbp, +uint32_t feature) {return (sbp->sb_features_log_incompat & feature) !=0 ; }
@@ -420,7 +420,7 @@ xfs_sb_add_incompat_log_features( sbp->sb_features_log_incompat |= features; } -static inline bool xfs_sb_version_haslogxattrs (struct xfs_sb *sbp) +static inline bool xfs_sb_version_haslogxattrs (const struct xfs_sb *sbp) {return xfs_sb_is_v5 (sbp) && (sbp->sb_features_log_incompat &XFS_SB_FEAT_INCOMPAT_LOG_XATTRS );
PATCH 2/29 xfs: constify the xfs_inode predicates
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
Change the xfs_inode predicates to take a const struct xfs_inode pointer because they do not change the inode.
--- fs/xfs/xfs_inode.c | 2 +- fs/xfs/xfs_inode.h | 20 ++++++++++---------- 2 files changed, 11 insertions(+), 11 deletions(-)
fs/xfs/xfs_inode.c +1 -1
@@ -3040,7 +3040,7 @@ xfs_inode_alloc_unitsize(/* Should we always be using copy on write for file writes? */ bool xfs_is_always_cow_inode ( -struct xfs_inode *ip) +const struct xfs_inode *ip) {return ip->i_mount->m_always_cow &&xfs_has_reflink (ip->i_mount); }
fs/xfs/xfs_inode.h +10 -10
@@ -100,7 +100,7 @@ static inline bool xfs_inode_on_unlinked_list(const struct xfs_inode *ip)return ip->i_prev_unlinked !=0 ; } -static inline bool xfs_inode_has_attr_fork (struct xfs_inode *ip) +static inline bool xfs_inode_has_attr_fork (const struct xfs_inode *ip) {return ip->i_forkoff >0 ; }
@@ -271,7 +271,7 @@ xfs_iflags_test_and_set(xfs_inode_t *ip, unsigned long flags)return ret; } -static inline bool xfs_is_reflink_inode (struct xfs_inode *ip) +static inline bool xfs_is_reflink_inode (const struct xfs_inode *ip) {return ip->i_diflags2 &XFS_DIFLAG2_REFLINK ; }
@@ -285,9 +285,9 @@ static inline bool xfs_is_metadata_inode(const struct xfs_inode *ip)xfs_is_quota_inode (&mp->m_sb, ip->i_ino); } -bool xfs_is_always_cow_inode (struct xfs_inode *ip); +bool xfs_is_always_cow_inode (const struct xfs_inode *ip); -static inline bool xfs_is_cow_inode (struct xfs_inode *ip) +static inline bool xfs_is_cow_inode (const struct xfs_inode *ip) {return xfs_is_reflink_inode (ip) ||xfs_is_always_cow_inode (ip); }
@@ -296,17 +296,17 @@ static inline bool xfs_is_cow_inode(struct xfs_inode *ip)* Check if an inode has any data in the COW fork. This might be often false * even for inodes with the reflink flag when there is no pending COW operation. */ -static inline bool xfs_inode_has_cow_data (struct xfs_inode *ip) +static inline bool xfs_inode_has_cow_data (const struct xfs_inode *ip) {return ip->i_cowfp && ip->i_cowfp->if_bytes; } -static inline bool xfs_inode_has_bigtime (struct xfs_inode *ip) +static inline bool xfs_inode_has_bigtime (const struct xfs_inode *ip) {return ip->i_diflags2 &XFS_DIFLAG2_BIGTIME ; } -static inline bool xfs_inode_has_large_extent_counts (struct xfs_inode *ip) +static inline bool xfs_inode_has_large_extent_counts (const struct xfs_inode *ip) {return ip->i_diflags2 &XFS_DIFLAG2_NREXT64 ; }
@@ -315,7 +315,7 @@ static inline bool xfs_inode_has_large_extent_counts(struct xfs_inode *ip)* Decide if this file is a realtime file whose data allocation unit is larger * than a single filesystem block. */ -static inline bool xfs_inode_has_bigrtalloc (struct xfs_inode *ip) +static inline bool xfs_inode_has_bigrtalloc (const struct xfs_inode *ip) {return XFS_IS_REALTIME_INODE (ip) && ip->i_mount->m_sb.sb_rextsize >1 ; }
@@ -620,9 +620,9 @@ void xfs_sort_inodes(struct xfs_inode **i_tab, unsigned int num_inodes);static inline bool xfs_inode_unlinked_incomplete ( -struct xfs_inode *ip) +const struct xfs_inode *ip) { -return VFS_I (ip)->i_nlink ==0 && !xfs_inode_on_unlinked_list (ip); +return VFS_IC (ip)->i_nlink ==0 && !xfs_inode_on_unlinked_list (ip); }int xfs_inode_reload_unlinked_bucket (struct xfs_trans *tp,struct xfs_inode *ip);int xfs_inode_reload_unlinked (struct xfs_inode *ip);
PATCH 3/29 xfs: rename metadata inode predicates
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
The predicate xfs_internal_inum tells us if an inumber refers to one of the inodes rooted in the superblock. Soon we're going to have internal inodes in a metadata directory tree, so this helper should be renamed to capture its limited scope.
Ondisk inodes will soon have a flag to indicate that they're metadata inodes. Head off some confusion by renaming the xfs_is_metadata_inode predicate to xfs_is_internal_inode.
--- fs/xfs/libxfs/xfs_types.c | 4 ++-- fs/xfs/libxfs/xfs_types.h | 2 +- fs/xfs/scrub/common.c | 2 +- fs/xfs/scrub/inode.c | 2 +- fs/xfs/scrub/inode_repair.c | 2 +- fs/xfs/scrub/orphanage.c | 2 +- fs/xfs/scrub/parent.c | 2 +- fs/xfs/scrub/refcount_repair.c | 2 +- fs/xfs/xfs_inode.c | 4 ++-- fs/xfs/xfs_inode.h | 2 +- fs/xfs/xfs_itable.c | 2 +- 11 files changed, 13 insertions(+), 13 deletions(-)
fs/xfs/libxfs/xfs_types.c +2 -2
@@ -111,7 +111,7 @@ xfs_verify_ino(/* Is this an internal inode number? */ inline bool -xfs_internal_inum ( +xfs_is_sb_inum (struct xfs_mount *mp,xfs_ino_t ino) {
@@ -129,7 +129,7 @@ xfs_verify_dir_ino( struct xfs_mount *mp, xfs_ino_t ino) { - if (xfs_internal_inum(mp, ino)) + if (xfs_is_sb_inum(mp, ino)) return false;return xfs_verify_ino (mp, ino); }
fs/xfs/libxfs/xfs_types.h +1 -1
@@ -230,7 +230,7 @@ bool xfs_verify_fsbext(struct xfs_mount *mp, xfs_fsblock_t fsbno, xfs_fsblock_t len);bool xfs_verify_ino (struct xfs_mount *mp,xfs_ino_t ino); -bool xfs_internal_inum (struct xfs_mount *mp,xfs_ino_t ino); +bool xfs_is_sb_inum (struct xfs_mount *mp,xfs_ino_t ino);bool xfs_verify_dir_ino (struct xfs_mount *mp,xfs_ino_t ino);bool xfs_verify_rtbno (struct xfs_mount *mp,xfs_rtblock_t rtbno); bool xfs_verify_rtbext(struct xfs_mount *mp, xfs_rtblock_t rtbno,
fs/xfs/scrub/common.c +1 -1
@@ -948,7 +948,7 @@ xchk_iget_for_scrubbing(return xchk_install_live_inode (sc, ip_in);/* Reject internal metadata files and obviously bad inode numbers. */ -if (xfs_internal_inum (mp, sc->sm->sm_ino)) +if (xfs_is_sb_inum (mp, sc->sm->sm_ino))return -ENOENT ;if (!xfs_verify_ino (sc->mp, sc->sm->sm_ino))return -ENOENT ;
fs/xfs/scrub/inode.c +1 -1
@@ -95,7 +95,7 @@ xchk_setup_inode( }/* Reject internal metadata files and obviously bad inode numbers. */ -if (xfs_internal_inum (mp, sc->sm->sm_ino)) +if (xfs_is_sb_inum (mp, sc->sm->sm_ino))return -ENOENT ;if (!xfs_verify_ino (sc->mp, sc->sm->sm_ino))return -ENOENT ;
fs/xfs/scrub/inode_repair.c +1 -1
@@ -1762,7 +1762,7 @@ xrep_inode_pptr(* Metadata inodes are rooted in the superblock and do not have any * parents. */ -if (xfs_is_metadata_inode (ip)) +if (xfs_is_internal_inode (ip))return 0 ;/* Inode already has an attr fork; no further work possible here. */
fs/xfs/scrub/orphanage.c +1 -1
@@ -295,7 +295,7 @@ xrep_orphanage_can_adopt(return false;if (sc->ip == sc->orphanage)return false; -if (xfs_internal_inum (sc->mp, sc->ip->i_ino)) +if (xfs_is_sb_inum (sc->mp, sc->ip->i_ino))return false;return true; }
fs/xfs/scrub/parent.c +1 -1
@@ -910,7 +910,7 @@ xchk_pptr_looks_zapped(* any parents. Hence the attr fork will not be initialized, but * there are no parent pointers that might have been zapped. */ -if (xfs_is_metadata_inode (ip)) +if (xfs_is_internal_inode (ip))return false;/*
fs/xfs/scrub/refcount_repair.c +1 -1
@@ -215,7 +215,7 @@ xrep_refc_rmap_shareable(return false;/* Metadata in files are never shareable */ -if (xfs_internal_inum (mp, rmap->rm_owner)) +if (xfs_is_sb_inum (mp, rmap->rm_owner))return false;/* Metadata and unwritten file blocks are not shareable. */
fs/xfs/xfs_inode.c +2 -2
@@ -1295,7 +1295,7 @@ xfs_inode_needs_inactive(return false;/* Metadata inodes require explicit resource cleanup. */ -if (xfs_is_metadata_inode (ip)) +if (xfs_is_internal_inode (ip))return false;/* Want to clean out the cow blocks if there are any. */
@@ -1388,7 +1388,7 @@ xfs_inactive( goto out;/* Metadata inodes require explicit resource cleanup. */ -if (xfs_is_metadata_inode (ip)) +if (xfs_is_internal_inode (ip)) goto out;/* Try to clean out the cow blocks if there are any. */
fs/xfs/xfs_inode.h +1 -1
@@ -276,7 +276,7 @@ static inline bool xfs_is_reflink_inode(const struct xfs_inode *ip)return ip->i_diflags2 &XFS_DIFLAG2_REFLINK ; } -static inline bool xfs_is_metadata_inode (const struct xfs_inode *ip) +static inline bool xfs_is_internal_inode (const struct xfs_inode *ip) {struct xfs_mount *mp = ip->i_mount;
fs/xfs/xfs_itable.c +1 -1
@@ -69,7 +69,7 @@ xfs_bulkstat_one_int(vfsuid_t vfsuid;vfsgid_t vfsgid; -if (xfs_internal_inum (mp, ino)) +if (xfs_is_sb_inum (mp, ino)) goto out_advance; error = xfs_iget(mp, tp, ino,
Re: [PATCH 03/29] xfs: rename metadata inode predicates
Quoted 10 lines · Darrick J. Wong
From: Darrick J. Wong <[email protected]>
The predicate
xfs_internal_inumtells us if an inumber refers to one of the inodes rooted in the superblock. Soon we're going to have internal inodes in a metadata directory tree, so this helper should be renamed to capture its limited scope.Ondisk inodes will soon have a flag to indicate that they're metadata inodes. Head off some confusion by renaming the
xfs_is_metadata_inodepredicate toxfs_is_internal_inode.
I don't really care either way, but the patch looks correct:
PATCH 4/29 xfs: standardize EXPERIMENTAL warning generation
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
Refactor the open-coded warnings about EXPERIMENTAL feature use into a standard helper before we go adding more experimental features.
--- fs/xfs/scrub/scrub.c | 3 +-- fs/xfs/xfs_fsops.c | 4 +--- fs/xfs/xfs_message.c | 43 +++++++++++++++++++++++++++++++++++++++++++ fs/xfs/xfs_message.h | 18 ++++++++++++------ fs/xfs/xfs_mount.h | 6 ++++++ fs/xfs/xfs_super.c | 10 +++------- fs/xfs/xfs_xattr.c | 3 +-- 7 files changed, 67 insertions(+), 20 deletions(-)
fs/xfs/scrub/scrub.c +1 -2
@@ -605,8 +605,7 @@ xfs_scrub_metadata(if (error) goto out; -xfs_warn_mount (mp,XFS_OPSTATE_WARNED_SCRUB , -"EXPERIMENTAL online scrub feature in use. Use at your own risk!" ); +xfs_warn_experimental (mp,XFS_EXPERIMENTAL_SCRUB ); sc =kzalloc (sizeof (struct xfs_scrub ),XCHK_GFP_FLAGS );if (!sc) {
fs/xfs/xfs_fsops.c +1 -3
@@ -162,9 +162,7 @@ xfs_growfs_data_private( error =xfs_resizefs_init_new_ags (tp, &id, oagcount, nagcount, delta, last_pag, &lastag_extended); }else { -xfs_warn_mount (mp,XFS_OPSTATE_WARNED_SHRINK , -"EXPERIMENTAL online shrink feature in use. Use at your own risk!" ); - +xfs_warn_experimental (mp,XFS_EXPERIMENTAL_SHRINK ); error =xfs_ag_shrink_space (last_pag, &tp, -delta); }xfs_perag_put (last_pag);
fs/xfs/xfs_message.c +43 -0
46 lines not on this page · raw message
fs/xfs/xfs_message.h +12 -6
@@ -75,12 +75,6 @@ do { \#define xfs_debug_ratelimited (dev, fmt, ...) \ xfs_printk_ratelimited(xfs_debug, dev, fmt, ##__VA_ARGS__) -#define xfs_warn_mount (mp, warntag, fmt, ...) \ -do { \ - if (xfs_should_warn((mp), (warntag))) \ - xfs_warn((mp), (fmt), ##__VA_ARGS__); \ -} while (0) -#define xfs_warn_once (dev, fmt, ...) \ xfs_printk_once(xfs_warn, dev, fmt, ##__VA_ARGS__)#define xfs_notice_once (dev, fmt, ...) \
@@ -96,4 +90,16 @@ extern void xfs_hex_dump(const void *p, int length);void xfs_buf_alert_ratelimited (struct xfs_buf *bp,const char *rlmsg,const char *fmt, ...); +enum xfs_experimental_feat { +XFS_EXPERIMENTAL_SCRUB , +XFS_EXPERIMENTAL_SHRINK , +XFS_EXPERIMENTAL_LARP , +XFS_EXPERIMENTAL_LBS , +XFS_EXPERIMENTAL_EXCHRANGE , +XFS_EXPERIMENTAL_PPTR , + +XFS_EXPERIMENTAL_MAX , +}; +void xfs_warn_experimental (struct xfs_mount *mp,enum xfs_experimental_feat f); +#endif /* __XFS_MESSAGE_H */
fs/xfs/xfs_mount.h +6 -0
@@ -479,6 +479,12 @@ __XFS_HAS_FEAT(nouuid, NOUUID)#define XFS_OPSTATE_UNSET_LOG_INCOMPAT 11/* Filesystem can use logged extended attributes */ #define XFS_OPSTATE_USE_LARP 12 +/* Kernel has logged a warning about blocksize > pagesize on this fs. */ +#define XFS_OPSTATE_WARNED_LBS 13 +/* Kernel has logged a warning about exchange-range being used on this fs. */ +#define XFS_OPSTATE_WARNED_EXCHRANGE 14 +/* Kernel has logged a warning about parent pointers being used on this fs. */ +#define XFS_OPSTATE_WARNED_PPTR 15#define __XFS_IS_OPSTATE (name,NAME ) \ static inline bool xfs_is_ ## name (struct xfs_mount *mp) \
fs/xfs/xfs_super.c +3 -7
@@ -1657,9 +1657,7 @@ xfs_fs_fill_super( goto out_free_sb; } -xfs_warn (mp, -"EXPERIMENTAL: V5 Filesystem with Large Block Size (%d bytes) enabled." , - mp->m_sb.sb_blocksize); +xfs_warn_experimental (mp,XFS_EXPERIMENTAL_LBS ); }/* Ensure this filesystem fits in the page cache limits */
@@ -1755,12 +1753,10 @@ xfs_fs_fill_super( }if (xfs_has_exchange_range (mp)) -xfs_warn (mp, -"EXPERIMENTAL exchange-range feature enabled. Use at your own risk!" ); +xfs_warn_experimental (mp,XFS_EXPERIMENTAL_EXCHRANGE );if (xfs_has_parent (mp)) -xfs_warn (mp, -"EXPERIMENTAL parent pointer feature enabled. Use at your own risk!" ); +xfs_warn_experimental (mp,XFS_EXPERIMENTAL_PPTR ); error =xfs_mountfs (mp);if (error)
fs/xfs/xfs_xattr.c +1 -2
@@ -51,8 +51,7 @@ xfs_attr_grab_log_assist(return error;xfs_set_using_logged_xattrs (mp); -xfs_warn_mount (mp,XFS_OPSTATE_WARNED_LARP , -"EXPERIMENTAL logged extended attributes feature in use. Use at your own risk!" ); +xfs_warn_experimental (mp,XFS_EXPERIMENTAL_LARP );return 0 ; }
Re: [PATCH 04/29] xfs: standardize EXPERIMENTAL warning generation
Quoted 4 lines · Darrick J. Wong
From: Darrick J. Wong <[email protected]>
Refactor the open-coded warnings about EXPERIMENTAL feature use into a standard helper before we go adding more experimental features.
Feels like a bit of overkill, but the code looks fine:
PATCH 5/29 xfs: define the on-disk format for the metadir feature
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
Define the on-disk layout and feature flags for the metadata inode directory feature. Add a xfs_sb_version_hasmetadir for benefit of xfs_repair, which needs to know where the new end of the superblock lies.
--- fs/xfs/libxfs/xfs_format.h | 97 ++++++++++++++++++++++++++++++++++----- fs/xfs/libxfs/xfs_inode_buf.c | 20 ++++++-- fs/xfs/libxfs/xfs_inode_util.c | 2 + fs/xfs/libxfs/xfs_log_format.h | 2 - fs/xfs/libxfs/xfs_ondisk.h | 2 - fs/xfs/libxfs/xfs_sb.c | 10 ++++ fs/xfs/scrub/inode.c | 2 - fs/xfs/scrub/inode_repair.c | 9 ++-- fs/xfs/xfs_inode.h | 14 ++++++ fs/xfs/xfs_inode_item.c | 7 ++- fs/xfs/xfs_inode_item_recover.c | 2 - fs/xfs/xfs_message.c | 4 ++ fs/xfs/xfs_message.h | 1 fs/xfs/xfs_mount.h | 4 ++ fs/xfs/xfs_super.c | 3 + 15 files changed, 153 insertions(+), 26 deletions(-)
fs/xfs/libxfs/xfs_format.h +84 -13
@@ -174,6 +174,8 @@ typedef struct xfs_sb {xfs_lsn_t sb_lsn;/* last write sequence */ uuid_t sb_meta_uuid;/* metadata file system unique id */ +xfs_ino_t sb_metadirino;/* metadata directory tree root */ +/* must be padded to 64 bit alignment */ } xfs_sb_t;
@@ -259,6 +261,8 @@ struct xfs_dsb {__be64 sb_lsn;/* last write sequence */ uuid_t sb_meta_uuid;/* metadata file system unique id */ +__be64 sb_metadirino;/* metadata directory tree root */ +/* must be padded to 64 bit alignment */ };
@@ -374,6 +378,7 @@ xfs_sb_has_ro_compat_feature(#define XFS_SB_FEAT_INCOMPAT_NREXT64 (1 << 5)/* large extent counters */ #define XFS_SB_FEAT_INCOMPAT_EXCHRANGE (1 << 6)/* exchangerange supported */ #define XFS_SB_FEAT_INCOMPAT_PARENT (1 << 7)/* parent pointers */ +#define XFS_SB_FEAT_INCOMPAT_METADIR (1 << 8)/* metadata dir tree */ #define XFS_SB_FEAT_INCOMPAT_ALL \ (XFS_SB_FEAT_INCOMPAT_FTYPE | \ XFS_SB_FEAT_INCOMPAT_SPINODES | \
@@ -790,6 +795,27 @@ static inline time64_t xfs_bigtime_to_unix(uint64_t ondisk_seconds)return (time64_t )ondisk_seconds -XFS_BIGTIME_EPOCH_OFFSET ; } +enum xfs_metafile_type { +XFS_METAFILE_UNKNOWN ,/* unknown */ +XFS_METAFILE_DIR ,/* metadir directory */ +XFS_METAFILE_USRQUOTA ,/* user quota */ +XFS_METAFILE_GRPQUOTA ,/* group quota */ +XFS_METAFILE_PRJQUOTA ,/* project quota */ +XFS_METAFILE_RTBITMAP ,/* rt bitmap */ +XFS_METAFILE_RTSUMMARY ,/* rt summary */ + +XFS_METAFILE_MAX +} __packed; + +#define XFS_METAFILE_TYPE_STR \ + { XFS_METAFILE_UNKNOWN, "unknown" }, \ + { XFS_METAFILE_DIR, "dir" }, \ + { XFS_METAFILE_USRQUOTA, "usrquota" }, \ + { XFS_METAFILE_GRPQUOTA, "grpquota" }, \ + { XFS_METAFILE_PRJQUOTA, "prjquota" }, \ + { XFS_METAFILE_RTBITMAP, "rtbitmap" }, \ + { XFS_METAFILE_RTSUMMARY, "rtsummary" } +/* * On-disk inode structure. *
@@ -812,7 +838,7 @@ struct xfs_dinode {__be16 di_mode;/* mode and type of file */ __u8 di_version;/* inode version */ __u8 di_format;/* format of di_c data */ -__be16 di_onlink;/* old number of links to file */ +__be16 di_metatype;/* XFS_METAFILE_*; was di_onlink */ __be32 di_uid;/* owner's user id */ __be32 di_gid;/* owner's group id */ __be32 di_nlink;/* number of links to file */
@@ -1088,21 +1114,60 @@ static inline void xfs_dinode_put_rdev(struct xfs_dinode *dip, xfs_dev_t rdev)* Values for di_flags2 These start by being exposed to userspace in the upper * 16 bits of the XFS_XFLAG_s range. */ -#define XFS_DIFLAG2_DAX_BIT 0/* use DAX for this inode */ -#define XFS_DIFLAG2_REFLINK_BIT 1/* file's blocks may be shared */ -#define XFS_DIFLAG2_COWEXTSIZE_BIT 2/* copy on write extent size hint */ -#define XFS_DIFLAG2_BIGTIME_BIT 3/* big timestamps */ -#define XFS_DIFLAG2_NREXT64_BIT 4/* large extent counters */ - -#define XFS_DIFLAG2_DAX (1 << XFS_DIFLAG2_DAX_BIT) -#define XFS_DIFLAG2_REFLINK (1 << XFS_DIFLAG2_REFLINK_BIT) -#define XFS_DIFLAG2_COWEXTSIZE (1 << XFS_DIFLAG2_COWEXTSIZE_BIT) -#define XFS_DIFLAG2_BIGTIME (1 << XFS_DIFLAG2_BIGTIME_BIT) -#define XFS_DIFLAG2_NREXT64 (1 << XFS_DIFLAG2_NREXT64_BIT) +/* use DAX for this inode */ +#define XFS_DIFLAG2_DAX_BIT 0 + +/* file's blocks may be shared */ +#define XFS_DIFLAG2_REFLINK_BIT 1 + +/* copy on write extent size hint */ +#define XFS_DIFLAG2_COWEXTSIZE_BIT 2 + +/* big timestamps */ +#define XFS_DIFLAG2_BIGTIME_BIT 3 + +/* large extent counters */ +#define XFS_DIFLAG2_NREXT64_BIT 4 + +/* +* The inode contains filesystem metadata and can be found through the metadata +* directory tree. Metadata inodes must satisfy the following constraints: +* +* - V5 filesystem (and ftype) are enabled; +* - The only valid modes are regular files and directories; +* - The access bits must be zero; +* - DMAPI event and state masks are zero; +* - The user and group IDs must be zero; +* - The project ID can be used as a u32 annotation; +* - The immutable, sync, noatime, nodump, nodefrag flags must be set. +* - The dax flag must not be set. +* - Directories must have nosymlinks set. +* +* These requirements are chosen defensively to minimize the ability of +* userspace to read or modify the contents, should a metadata file ever +* escape to userspace. +* +* There are further constraints on the directory tree itself: +* +* - Metadata inodes must never be resolvable through the root directory; +* - They must never be accessed by userspace; +* - Metadata directory entries must have correct ftype. +* +* Superblock-rooted metadata files must have the METADATA iflag set even +* though they do not have a parent directory. +*/ +#define XFS_DIFLAG2_METADATA_BIT 5 + +#define XFS_DIFLAG2_DAX (1ULL << XFS_DIFLAG2_DAX_BIT) +#define XFS_DIFLAG2_REFLINK (1ULL << XFS_DIFLAG2_REFLINK_BIT) +#define XFS_DIFLAG2_COWEXTSIZE (1ULL << XFS_DIFLAG2_COWEXTSIZE_BIT) +#define XFS_DIFLAG2_BIGTIME (1ULL << XFS_DIFLAG2_BIGTIME_BIT) +#define XFS_DIFLAG2_NREXT64 (1ULL << XFS_DIFLAG2_NREXT64_BIT) +#define XFS_DIFLAG2_METADATA (1ULL << XFS_DIFLAG2_METADATA_BIT)#define XFS_DIFLAG2_ANY \ (XFS_DIFLAG2_DAX | XFS_DIFLAG2_REFLINK | XFS_DIFLAG2_COWEXTSIZE | \ - XFS_DIFLAG2_BIGTIME | XFS_DIFLAG2_NREXT64) + XFS_DIFLAG2_BIGTIME | XFS_DIFLAG2_NREXT64 | XFS_DIFLAG2_METADATA)static inline bool xfs_dinode_has_bigtime (const struct xfs_dinode *dip) {
@@ -1117,6 +1182,12 @@ static inline bool xfs_dinode_has_large_extent_counts( (dip->di_flags2 &cpu_to_be64 (XFS_DIFLAG2_NREXT64 )); } +static inline bool xfs_dinode_is_metadir (const struct xfs_dinode *dip) +{ +return dip->di_version >=3 && + (dip->di_flags2 &cpu_to_be64 (XFS_DIFLAG2_METADATA )); +} +/* * Inode number format: * low inopblog bits - offset in block
fs/xfs/libxfs/xfs_inode_buf.c +15 -5
@@ -209,12 +209,15 @@ xfs_inode_from_disk(* They will also be unconditionally written back to disk as v2 inodes. */ if (unlikely (from->di_version ==1 )) { -set_nlink (inode,be16_to_cpu (from->di_onlink)); +/* di_metatype used to be di_onlink */ +set_nlink (inode,be16_to_cpu (from->di_metatype)); ip->i_projid =0 ; }else {set_nlink (inode,be32_to_cpu (from->di_nlink)); ip->i_projid = (prid_t )be16_to_cpu (from->di_projid_hi) <<16 |be16_to_cpu (from->di_projid_lo); +if (xfs_dinode_is_metadir (from)) + ip->i_metatype =be16_to_cpu (from->di_metatype); }i_uid_write (inode,be32_to_cpu (from->di_uid));
@@ -315,7 +318,10 @@ xfs_inode_to_disk(struct inode *inode =VFS_I (ip); to->di_magic =cpu_to_be16 (XFS_DINODE_MAGIC ); - to->di_onlink =0 ; +if (xfs_is_metadir_inode (ip)) + to->di_metatype =cpu_to_be16 (ip->i_metatype); +else + to->di_metatype =0 ; to->di_format =xfs_ifork_format (&ip->i_df); to->di_uid =cpu_to_be32 (i_uid_read (inode));
@@ -523,8 +529,11 @@ xfs_dinode_verify(* di_nlink==0 on a V1 inode. V2/3 inodes would get written out with * di_onlink==0, so we can check that. */ -if (dip->di_version >=2 ) { -if (dip->di_onlink) +if (dip->di_version ==2 ) { +if (dip->di_metatype) +return __this_address; + }else if (dip->di_version >=3 ) { +if (!xfs_dinode_is_metadir (dip) && dip->di_metatype)return __this_address; }
@@ -546,7 +555,8 @@ xfs_dinode_verify(if (dip->di_nlink)return __this_address; }else { -if (dip->di_onlink) +/* di_metatype used to be di_onlink */ +if (dip->di_metatype)return __this_address; } }
fs/xfs/libxfs/xfs_inode_util.c +2 -0
@@ -224,6 +224,8 @@ xfs_inode_inherit_flags2( }if (pip->i_diflags2 &XFS_DIFLAG2_DAX ) ip->i_diflags2 |=XFS_DIFLAG2_DAX ; +if (xfs_is_metadir_inode (pip)) + ip->i_diflags2 |=XFS_DIFLAG2_METADATA ;/* Don't let invalid cowextsize hints propagate. */ failaddr = xfs_inode_validate_cowextsize(ip->i_mount, ip->i_cowextsize,
fs/xfs/libxfs/xfs_log_format.h +1 -1
@@ -404,7 +404,7 @@ struct xfs_log_dinode {uint16_t di_mode;/* mode and type of file */ int8_t di_version;/* inode version */ int8_t di_format;/* format of di_c data */ -uint8_t di_pad3[2 ];/* unused in v2/3 inodes */ +uint16_t di_metatype;/* metadata type, if DIFLAG2_METADATA */ uint32_t di_uid;/* owner's user id */ uint32_t di_gid;/* owner's group id */ uint32_t di_nlink;/* number of links to file */
fs/xfs/libxfs/xfs_ondisk.h +1 -1
@@ -37,7 +37,7 @@ xfs_check_ondisk_structs(void) XFS_CHECK_STRUCT_SIZE(struct xfs_dinode, 176); XFS_CHECK_STRUCT_SIZE(struct xfs_disk_dquot, 104); XFS_CHECK_STRUCT_SIZE(struct xfs_dqblk, 136); - XFS_CHECK_STRUCT_SIZE(struct xfs_dsb, 264); + XFS_CHECK_STRUCT_SIZE(struct xfs_dsb, 272); XFS_CHECK_STRUCT_SIZE(struct xfs_dsymlink_hdr, 56); XFS_CHECK_STRUCT_SIZE(struct xfs_inobt_key, 4); XFS_CHECK_STRUCT_SIZE(struct xfs_inobt_rec, 16);
fs/xfs/libxfs/xfs_sb.c +10 -0
@@ -180,6 +180,8 @@ xfs_sb_version_to_features( features |=XFS_FEAT_EXCHANGE_RANGE ;if (sbp->sb_features_incompat &XFS_SB_FEAT_INCOMPAT_PARENT ) features |=XFS_FEAT_PARENT ; +if (sbp->sb_features_incompat &XFS_SB_FEAT_INCOMPAT_METADIR ) + features |=XFS_FEAT_METADIR ;return features; }
@@ -689,6 +691,11 @@ __xfs_sb_from_disk(/* Convert on-disk flags to in-memory flags? */ if (convert_xquota)xfs_sb_quota_from_disk (to); + +if (to->sb_features_incompat &XFS_SB_FEAT_INCOMPAT_METADIR ) + to->sb_metadirino =be64_to_cpu (from->sb_metadirino); +else + to->sb_metadirino =NULLFSINO ; }void
@@ -836,6 +843,9 @@ xfs_sb_to_disk( to->sb_lsn =cpu_to_be64 (from->sb_lsn);if (from->sb_features_incompat &XFS_SB_FEAT_INCOMPAT_META_UUID )uuid_copy (&to->sb_meta_uuid, &from->sb_meta_uuid); + +if (from->sb_features_incompat &XFS_SB_FEAT_INCOMPAT_METADIR ) + to->sb_metadirino =cpu_to_be64 (from->sb_metadirino); }/*
fs/xfs/scrub/inode.c +1 -1
@@ -421,7 +421,7 @@ xchk_dinode(break ;case 2 :case 3 : -if (dip->di_onlink !=0 ) +if (!xfs_dinode_is_metadir (dip) && dip->di_metatype)xchk_ino_set_corrupt (sc, ino);if (dip->di_mode ==0 && sc->ip)
fs/xfs/scrub/inode_repair.c +6 -3
@@ -521,10 +521,13 @@ STATIC voidxrep_dinode_nlinks ( struct xfs_dinode *dip) { -if (dip->di_version >1 ) - dip->di_onlink =0 ; -else +if (dip->di_version <2 ) { dip->di_nlink =0 ; +return ; + } + +if (!xfs_dinode_is_metadir (dip)) + dip->di_metatype =0 ; }/* Fix any conflicting flags that the verifiers complain about. */
fs/xfs/xfs_inode.h +14 -0
@@ -65,6 +65,7 @@ typedef struct xfs_inode {uint16_t i_flushiter;/* incremented on flush */ };uint8_t i_forkoff;/* attr fork offset >> 3 */ +enum xfs_metafile_type i_metatype;/* XFS_METAFILE_* */ uint16_t i_diflags;/* XFS_DIFLAG_... */ uint64_t i_diflags2;/* XFS_DIFLAG2_... */ struct timespec64 i_crtime;/* time created */
@@ -276,10 +277,23 @@ static inline bool xfs_is_reflink_inode(const struct xfs_inode *ip)return ip->i_diflags2 &XFS_DIFLAG2_REFLINK ; } +static inline bool xfs_is_metadir_inode (const struct xfs_inode *ip) +{ +return ip->i_diflags2 &XFS_DIFLAG2_METADATA ; +} +static inline bool xfs_is_internal_inode (const struct xfs_inode *ip) {struct xfs_mount *mp = ip->i_mount; +/* Any file in the metadata directory tree is a metadata inode. */ +if (xfs_has_metadir (mp)) +return xfs_is_metadir_inode (ip); + +/* +* Before metadata directories, the only metadata inodes were the +* three quota files, the realtime bitmap, and the realtime summary. +*/ return ip->i_ino == mp->m_sb.sb_rbmino || ip->i_ino == mp->m_sb.sb_rsumino ||xfs_is_quota_inode (&mp->m_sb, ip->i_ino);
fs/xfs/xfs_inode_item.c +6 -1
@@ -556,7 +556,6 @@ xfs_inode_to_log_dinode( to->di_projid_lo = ip->i_projid &0xffff ; to->di_projid_hi = ip->i_projid >>16 ; -memset (to->di_pad3,0 ,sizeof (to->di_pad3)); to->di_atime =xfs_inode_to_log_dinode_ts (ip,inode_get_atime (inode)); to->di_mtime =xfs_inode_to_log_dinode_ts (ip,inode_get_mtime (inode)); to->di_ctime =xfs_inode_to_log_dinode_ts (ip,inode_get_ctime (inode));
@@ -590,10 +589,16 @@ xfs_inode_to_log_dinode(/* dummy value for initialisation */ to->di_crc =0 ; + +if (xfs_is_metadir_inode (ip)) + to->di_metatype = ip->i_metatype; +else + to->di_metatype =0 ; }else { to->di_version =2 ; to->di_flushiter = ip->i_flushiter;memset (to->di_v2_pad,0 ,sizeof (to->di_v2_pad)); + to->di_metatype =0 ; }xfs_inode_to_log_dinode_iext_counters (ip, to);
fs/xfs/xfs_inode_item_recover.c +1 -1
@@ -175,7 +175,7 @@ xfs_log_dinode_to_disk( to->di_mode =cpu_to_be16 (from->di_mode); to->di_version = from->di_version; to->di_format = from->di_format; - to->di_onlink =0 ; + to->di_metatype =cpu_to_be16 (from->di_metatype); to->di_uid =cpu_to_be32 (from->di_uid); to->di_gid =cpu_to_be32 (from->di_gid); to->di_nlink =cpu_to_be32 (from->di_nlink);
fs/xfs/xfs_message.c +4 -0
@@ -165,6 +165,10 @@ xfs_warn_experimental( .opstate = XFS_OPSTATE_WARNED_PPTR, .name = "parent pointer", }, + [XFS_EXPERIMENTAL_METADIR] = { + .opstate = XFS_OPSTATE_WARNED_METADIR, + .name = "metadata directory tree", + }, };ASSERT (feat >=0 && feat <XFS_EXPERIMENTAL_MAX );BUILD_BUG_ON (ARRAY_SIZE (features) !=XFS_EXPERIMENTAL_MAX );
fs/xfs/xfs_message.h +1 -0
@@ -97,6 +97,7 @@ enum xfs_experimental_feat {XFS_EXPERIMENTAL_LBS ,XFS_EXPERIMENTAL_EXCHRANGE ,XFS_EXPERIMENTAL_PPTR , +XFS_EXPERIMENTAL_METADIR , XFS_EXPERIMENTAL_MAX, };
fs/xfs/xfs_mount.h +4 -0
@@ -332,6 +332,7 @@ typedef struct xfs_mount {#define XFS_FEAT_NEEDSREPAIR (1ULL << 25)/* needs xfs_repair */ #define XFS_FEAT_NREXT64 (1ULL << 26)/* large extent counters */ #define XFS_FEAT_EXCHANGE_RANGE (1ULL << 27)/* exchange range */ +#define XFS_FEAT_METADIR (1ULL << 28)/* metadata directory tree */ /* Mount features */ #define XFS_FEAT_NOATTR2 (1ULL << 48)/* disable attr2 creation */
@@ -387,6 +388,7 @@ __XFS_HAS_FEAT(bigtime, BIGTIME) __XFS_HAS_FEAT(needsrepair, NEEDSREPAIR) __XFS_HAS_FEAT(large_extent_counts, NREXT64) __XFS_HAS_FEAT(exchange_range, EXCHANGE_RANGE) +__XFS_HAS_FEAT (metadir,METADIR )/* * Some features are always on for v5 file systems, allow the compiler to
@@ -485,6 +487,8 @@ __XFS_HAS_FEAT(nouuid, NOUUID)#define XFS_OPSTATE_WARNED_EXCHRANGE 14/* Kernel has logged a warning about parent pointers being used on this fs. */ #define XFS_OPSTATE_WARNED_PPTR 15 +/* Kernel has logged a warning about metadata dirs being used on this fs. */ +#define XFS_OPSTATE_WARNED_METADIR 16#define __XFS_IS_OPSTATE (name,NAME ) \ static inline bool xfs_is_ ## name (struct xfs_mount *mp) \
fs/xfs/xfs_super.c +3 -0
@@ -1731,6 +1731,9 @@ xfs_fs_fill_super( mp->m_features &= ~XFS_FEAT_DISCARD ; } +if (xfs_has_metadir (mp)) +xfs_warn_experimental (mp,XFS_EXPERIMENTAL_METADIR ); +if (xfs_has_reflink (mp)) {if (mp->m_sb.sb_rblocks) { xfs_alert(mp,
PATCH 6/29 xfs: iget for metadata inodes
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
Create a xfs_trans_metafile_iget function for metadata inodes to ensure that when we try to iget a metadata file, the inode is allocated and its file mode matches the metadata file type the caller expects.
--- fs/xfs/libxfs/xfs_metafile.h | 16 ++++++++++ fs/xfs/xfs_icache.c | 65 ++++++++++++++++++++++++++++++++++++++++++ fs/xfs/xfs_inode.c | 1 + fs/xfs/xfs_qm.c | 23 ++++++++++++++- fs/xfs/xfs_rtalloc.c | 38 ++++++++++++++----------- 5 files changed, 125 insertions(+), 18 deletions(-) create mode 100644 fs/xfs/libxfs/xfs_metafile.h
fs/xfs/libxfs/xfs_metafile.h new file +16 -0
@@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* +* Copyright (c) 2018-2024 Oracle. All Rights Reserved. +* Author: Darrick J. Wong <[email protected]> +*/ +#ifndef __XFS_METAFILE_H__ +#define __XFS_METAFILE_H__ + +/* Code specific to kernel/userspace; must be provided externally. */ + +int xfs_trans_metafile_iget (struct xfs_trans *tp,xfs_ino_t ino, +enum xfs_metafile_type metafile_type,struct xfs_inode **ipp); +int xfs_metafile_iget (struct xfs_mount *mp,xfs_ino_t ino, +enum xfs_metafile_type metafile_type,struct xfs_inode **ipp); + +#endif /* __XFS_METAFILE_H__ */
fs/xfs/xfs_icache.c +65 -0
77 lines not on this page · raw message
fs/xfs/xfs_inode.c +1 -0
@@ -43,6 +43,7 @@#include "xfs_parent.h" #include "xfs_xattr.h" #include "xfs_inode_util.h" +#include "xfs_metafile.h" struct kmem_cache *xfs_inode_cache;
fs/xfs/xfs_qm.c +21 -2
@@ -27,6 +27,8 @@#include "xfs_ialloc.h" #include "xfs_log_priv.h" #include "xfs_health.h" +#include "xfs_da_format.h" +#include "xfs_metafile.h" /* * The global quota manager. There is only one of these for the entire
@@ -733,6 +735,17 @@ xfs_qm_destroy_quotainfo( mp->m_quotainfo =NULL ; } +static inline enum xfs_metafile_type +xfs_qm_metafile_type ( +unsigned int flags) +{ +if (flags &XFS_QMOPT_UQUOTA ) +return XFS_METAFILE_USRQUOTA ; +else if (flags &XFS_QMOPT_GQUOTA ) +return XFS_METAFILE_GRPQUOTA ; +return XFS_METAFILE_PRJQUOTA ; +} +/* * Create an inode and return with a reference already taken, but unlocked * This is how we create quota inodes
@@ -744,6 +757,7 @@ xfs_qm_qino_alloc( unsigned int flags) {struct xfs_trans *tp; +enum xfs_metafile_type metafile_type =xfs_qm_metafile_type (flags);int error;bool need_alloc = true;
@@ -777,9 +791,10 @@ xfs_qm_qino_alloc( } }if (ino !=NULLFSINO ) { - error =xfs_iget (mp,NULL , ino,0 ,0 , ipp); + error =xfs_metafile_iget (mp, ino, metafile_type, ipp);if (error)return error; + mp->m_sb.sb_gquotino =NULLFSINO ; mp->m_sb.sb_pquotino =NULLFSINO ; need_alloc = false;
@@ -1553,16 +1568,20 @@ xfs_qm_qino_load( struct xfs_inode **ipp) {xfs_ino_t ino =NULLFSINO ; +enum xfs_metafile_type metafile_type =XFS_METAFILE_UNKNOWN ;switch (type) {case XFS_DQTYPE_USER : ino = mp->m_sb.sb_uquotino; + metafile_type =XFS_METAFILE_USRQUOTA ;break ;case XFS_DQTYPE_GROUP : ino = mp->m_sb.sb_gquotino; + metafile_type =XFS_METAFILE_GRPQUOTA ;break ;case XFS_DQTYPE_PROJ : ino = mp->m_sb.sb_pquotino; + metafile_type =XFS_METAFILE_PRJQUOTA ;break ;default :ASSERT (0 );
@@ -1572,7 +1591,7 @@ xfs_qm_qino_load(if (ino ==NULLFSINO )return -ENOENT ; -return xfs_iget (mp,NULL , ino,0 ,0 , ipp); +return xfs_metafile_iget (mp, ino, metafile_type, ipp); }/*
fs/xfs/xfs_rtalloc.c +22 -16
@@ -25,6 +25,8 @@#include "xfs_quota.h" #include "xfs_log_priv.h" #include "xfs_health.h" +#include "xfs_da_format.h" +#include "xfs_metafile.h" /* * Return whether there are any free extents in the size range given
@@ -1101,16 +1103,12 @@ xfs_rtalloc_reinit_frextents(*/ static inline int xfs_rtmount_iread_extents ( +struct xfs_trans *tp,struct xfs_inode *ip,unsigned int lock_class) { -struct xfs_trans *tp;int error; - error =xfs_trans_alloc_empty (ip->i_mount, &tp); -if (error) -return error; -xfs_ilock (ip,XFS_ILOCK_EXCL | lock_class); error =xfs_iread_extents (tp, ip,XFS_DATA_FORK );
@@ -1125,7 +1123,6 @@ xfs_rtmount_iread_extents( out_unlock:xfs_iunlock (ip,XFS_ILOCK_EXCL | lock_class); -xfs_trans_cancel (tp);return error; }
@@ -1133,45 +1130,54 @@ xfs_rtmount_iread_extents(* Get the bitmap and summary inodes and the summary cache into the mount * structure at mount time. */ -int /* error */ +int xfs_rtmount_inodes ( -xfs_mount_t *mp)/* file system mount structure */ +struct xfs_mount *mp) { -int error;/* error return value */ -xfs_sb_t *sbp; +struct xfs_trans *tp; +struct xfs_sb *sbp = &mp->m_sb; +int error; - sbp = &mp->m_sb; - error =xfs_iget (mp,NULL , sbp->sb_rbmino,0 ,0 , &mp->m_rbmip); + error =xfs_trans_alloc_empty (mp, &tp); +if (error) +return error; + + error =xfs_trans_metafile_iget (tp, mp->m_sb.sb_rbmino, +XFS_METAFILE_RTBITMAP , &mp->m_rbmip);if (xfs_metadata_is_sick (error))xfs_rt_mark_sick (mp,XFS_SICK_RT_BITMAP );if (error) -return error; + goto out_trans;ASSERT (mp->m_rbmip !=NULL ); - error =xfs_rtmount_iread_extents (mp->m_rbmip,XFS_ILOCK_RTBITMAP ); + error =xfs_rtmount_iread_extents (tp, mp->m_rbmip,XFS_ILOCK_RTBITMAP );if (error) goto out_rele_bitmap; - error =xfs_iget (mp,NULL , sbp->sb_rsumino,0 ,0 , &mp->m_rsumip); + error =xfs_trans_metafile_iget (tp, mp->m_sb.sb_rsumino, +XFS_METAFILE_RTSUMMARY , &mp->m_rsumip);if (xfs_metadata_is_sick (error))xfs_rt_mark_sick (mp,XFS_SICK_RT_SUMMARY );if (error) goto out_rele_bitmap;ASSERT (mp->m_rsumip !=NULL ); - error =xfs_rtmount_iread_extents (mp->m_rsumip,XFS_ILOCK_RTSUM ); + error =xfs_rtmount_iread_extents (tp, mp->m_rsumip,XFS_ILOCK_RTSUM );if (error) goto out_rele_summary; error =xfs_alloc_rsum_cache (mp, sbp->sb_rbmblocks);if (error) goto out_rele_summary; +xfs_trans_cancel (tp);return 0 ; out_rele_summary:xfs_irele (mp->m_rsumip); out_rele_bitmap:xfs_irele (mp->m_rbmip); +out_trans: +xfs_trans_cancel (tp);return error; }
PATCH 7/29 xfs: load metadata directory root at mount time
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
Load the metadata directory root inode into memory at mount time and release it at unmount time.
--- fs/xfs/xfs_mount.c | 31 +++++++++++++++++++++++++++++-- fs/xfs/xfs_mount.h | 1 + 2 files changed, 30 insertions(+), 2 deletions(-)
fs/xfs/xfs_mount.c +29 -2
@@ -35,6 +35,7 @@#include "xfs_trace.h" #include "xfs_ag.h" #include "xfs_rtbitmap.h" +#include "xfs_metafile.h" #include "scrub/stats.h" static DEFINE_MUTEX (xfs_uuid_table_mutex);
@@ -620,6 +621,22 @@ xfs_mount_setup_inode_geom(xfs_ialloc_setup_geometry (mp); } +/* Mount the metadata directory tree root. */ +STATIC int +xfs_mount_setup_metadir ( +struct xfs_mount *mp) +{ +int error; + +/* Load the metadata directory root inode into memory. */ + error =xfs_metafile_iget (mp, mp->m_sb.sb_metadirino,XFS_METAFILE_DIR , + &mp->m_metadirip); +if (error) +xfs_warn (mp,"Failed to load metadir root directory, error %d" , + error); +return error; +} +/* Compute maximum possible height for per-AG btree types for this fs. */ static inline void xfs_agbtree_compute_maxlevels(
@@ -866,6 +883,12 @@ xfs_mountfs( mp->m_features |=XFS_FEAT_ATTR2 ; } +if (xfs_has_metadir (mp)) { + error =xfs_mount_setup_metadir (mp); +if (error) + goto out_free_metadir; + } +/* * Get and sanity-check the root inode. * Save the pointer to it in the mount structure.
@@ -876,7 +899,7 @@ xfs_mountfs(xfs_warn (mp,"Failed to read root inode 0x%llx, error %d" , sbp->sb_rootino, -error); - goto out_log_dealloc; + goto out_free_metadir; }ASSERT (rip !=NULL );
@@ -1018,6 +1041,9 @@ xfs_mountfs(xfs_irele (rip);/* Clean out dquots that might be in memory after quotacheck. */ xfs_qm_unmount (mp); + out_free_metadir: +if (mp->m_metadirip) +xfs_irele (mp->m_metadirip);/* * Inactivate all inodes that might still be in memory after a log
@@ -1039,7 +1065,6 @@ xfs_mountfs(* quota inodes. */ xfs_unmount_flush_inodes (mp); - out_log_dealloc:xfs_log_mount_cancel (mp); out_inodegc_shrinker:shrinker_free (mp->m_inodegc_shrinker);
@@ -1091,6 +1116,8 @@ xfs_unmountfs(xfs_qm_unmount_quotas (mp);xfs_rtunmount_inodes (mp);xfs_irele (mp->m_rootip); +if (mp->m_metadirip) +xfs_irele (mp->m_metadirip);xfs_unmount_flush_inodes (mp);
fs/xfs/xfs_mount.h +1 -0
@@ -127,6 +127,7 @@ typedef struct xfs_mount {struct xfs_inode *m_rbmip;/* pointer to bitmap inode */ struct xfs_inode *m_rsumip;/* pointer to summary inode */ struct xfs_inode *m_rootip;/* pointer to root directory */ +struct xfs_inode *m_metadirip;/* ptr to metadata directory */ struct xfs_quotainfo *m_quotainfo;/* disk quota information */ struct xfs_buftarg *m_ddev_targp;/* data device */ struct xfs_buftarg *m_logdev_targp;/* log device */
PATCH 8/29 xfs: enforce metadata inode flag
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
Add checks for the metadata inode flag so that we don't ever leak metadata inodes out to userspace, and we don't ever try to read a regular inode as metadata.
--- fs/xfs/libxfs/xfs_inode_buf.c | 70 +++++++++++++++++++++++++++++++++++++++++ fs/xfs/libxfs/xfs_inode_buf.h | 3 ++ fs/xfs/libxfs/xfs_metafile.h | 11 ++++++ fs/xfs/scrub/common.c | 10 +++++- fs/xfs/scrub/inode.c | 26 ++++++++++++++- fs/xfs/scrub/inode_repair.c | 10 ++++++ fs/xfs/xfs_icache.c | 12 ++++++- fs/xfs/xfs_inode.c | 11 ++++++ 8 files changed, 147 insertions(+), 6 deletions(-)
fs/xfs/libxfs/xfs_inode_buf.c +70 -0
@@ -19,6 +19,7 @@#include "xfs_ialloc.h" #include "xfs_dir2.h" #include "xfs_health.h" +#include "xfs_metafile.h" #include <linux/iversion.h>
@@ -489,6 +490,69 @@ xfs_dinode_verify_nrext64(return NULL ; } +/* +* Validate all the picky requirements we have for a file that claims to be +* filesystem metadata. +*/ +xfs_failaddr_t +xfs_dinode_verify_metadir ( +struct xfs_mount *mp, +struct xfs_dinode *dip, +uint16_t mode, +uint16_t flags, +uint64_t flags2) +{ +if (!xfs_has_metadir (mp)) +return __this_address; + +/* V5 filesystem only */ +if (dip->di_version <3 ) +return __this_address; + +if (be16_to_cpu (dip->di_metatype) >=XFS_METAFILE_MAX ) +return __this_address; + +/* V3 inode fields that are always zero */ +if ((flags2 &XFS_DIFLAG2_NREXT64 ) && dip->di_nrext64_pad) +return __this_address; +if (!(flags2 &XFS_DIFLAG2_NREXT64 ) && dip->di_flushiter) +return __this_address; + +/* Metadata files can only be directories or regular files */ +if (!S_ISDIR (mode) && !S_ISREG (mode)) +return __this_address; + +/* They must have zero access permissions */ +if (mode &0777 ) +return __this_address; + +/* DMAPI event and state masks are zero */ +if (dip->di_dmevmask || dip->di_dmstate) +return __this_address; + +/* +* User and group IDs must be zero. The project ID is used for +* grouping inodes. Metadata inodes are never accounted to quotas. +*/ +if (dip->di_uid || dip->di_gid) +return __this_address; + +/* Mandatory inode flags must be set */ +if (S_ISDIR (mode)) { +if ((flags &XFS_METADIR_DIFLAGS ) !=XFS_METADIR_DIFLAGS ) +return __this_address; + }else { +if ((flags &XFS_METAFILE_DIFLAGS ) !=XFS_METAFILE_DIFLAGS ) +return __this_address; + } + +/* dax flags2 must not be set */ +if (flags2 &XFS_DIFLAG2_DAX ) +return __this_address; + +return NULL ; +} + xfs_failaddr_t xfs_dinode_verify( struct xfs_mount *mp,
@@ -673,6 +737,12 @@ xfs_dinode_verify( !xfs_has_bigtime(mp))return __this_address; +if (flags2 &XFS_DIFLAG2_METADATA ) { + fa =xfs_dinode_verify_metadir (mp, dip, mode, flags, flags2); +if (fa) +return fa; + } +return NULL ; }
fs/xfs/libxfs/xfs_inode_buf.h +3 -0
@@ -28,6 +28,9 @@ int xfs_inode_from_disk(struct xfs_inode *ip, struct xfs_dinode *from);xfs_failaddr_t xfs_dinode_verify (struct xfs_mount *mp,xfs_ino_t ino,struct xfs_dinode *dip); +xfs_failaddr_t xfs_dinode_verify_metadir (struct xfs_mount *mp, +struct xfs_dinode *dip,uint16_t mode,uint16_t flags, +uint64_t flags2);xfs_failaddr_t xfs_inode_validate_extsize (struct xfs_mount *mp,uint32_t extsize,uint16_t mode,uint16_t flags); xfs_failaddr_t xfs_inode_validate_cowextsize(struct xfs_mount *mp,
fs/xfs/libxfs/xfs_metafile.h +11 -0
@@ -6,6 +6,17 @@#ifndef __XFS_METAFILE_H__#define __XFS_METAFILE_H__ +/* All metadata files must have these flags set. */ +#define XFS_METAFILE_DIFLAGS (XFS_DIFLAG_IMMUTABLE | \ + XFS_DIFLAG_SYNC | \ + XFS_DIFLAG_NOATIME | \ + XFS_DIFLAG_NODUMP | \ + XFS_DIFLAG_NODEFRAG) + +/* All metadata directories must have these flags set. */ +#define XFS_METADIR_DIFLAGS (XFS_METAFILE_DIFLAGS | \ + XFS_DIFLAG_NOSYMLINKS) +/* Code specific to kernel/userspace; must be provided externally. */ int xfs_trans_metafile_iget(struct xfs_trans *tp, xfs_ino_t ino,
fs/xfs/scrub/common.c +8 -2
@@ -947,9 +947,15 @@ xchk_iget_for_scrubbing(if (sc->sm->sm_ino ==0 || sc->sm->sm_ino == ip_in->i_ino)return xchk_install_live_inode (sc, ip_in); -/* Reject internal metadata files and obviously bad inode numbers. */ -if (xfs_is_sb_inum (mp, sc->sm->sm_ino)) +/* +* On pre-metadir filesystems, reject internal metadata files. For +* metadir filesystems, limited scrubbing of any file in the metadata +* directory tree by handle is allowed, because that is the only way to +* validate the lack of parent pointers in the sb-root metadata inodes. +*/ +if (!xfs_has_metadir (mp) &&xfs_is_sb_inum (mp, sc->sm->sm_ino))return -ENOENT ; +/* Reject obviously bad inode numbers. */ if (!xfs_verify_ino (sc->mp, sc->sm->sm_ino))return -ENOENT ;
fs/xfs/scrub/inode.c +24 -2
@@ -60,6 +60,22 @@ xchk_install_handle_iscrub(if (error)return error; +/* +* Don't allow scrubbing by handle of any non-directory inode records +* in the metadata directory tree. We don't know if any of the scans +* launched by this scrubber will end up indirectly trying to lock this +* file. +* +* Scrubbers of inode-rooted metadata files (e.g. quota files) will +* attach all the resources needed to scrub the inode and call +* xchk_inode directly. Userspace cannot call this directly. +*/ +if (xfs_is_metadir_inode (ip) && !S_ISDIR (VFS_I (ip)->i_mode)) { +xchk_irele (sc, ip); + sc->ip =NULL ; +return -ENOENT ; + } +return xchk_prepare_iscrub (sc); }
@@ -94,9 +110,15 @@ xchk_setup_inode(return xchk_prepare_iscrub (sc); } -/* Reject internal metadata files and obviously bad inode numbers. */ -if (xfs_is_sb_inum (mp, sc->sm->sm_ino)) +/* +* On pre-metadir filesystems, reject internal metadata files. For +* metadir filesystems, limited scrubbing of any file in the metadata +* directory tree by handle is allowed, because that is the only way to +* validate the lack of parent pointers in the sb-root metadata inodes. +*/ +if (!xfs_has_metadir (mp) &&xfs_is_sb_inum (mp, sc->sm->sm_ino))return -ENOENT ; +/* Reject obviously bad inode numbers. */ if (!xfs_verify_ino (sc->mp, sc->sm->sm_ino))return -ENOENT ;
fs/xfs/scrub/inode_repair.c +10 -0
@@ -568,6 +568,16 @@ xrep_dinode_flags( dip->di_nrext64_pad =0 ; else if (dip->di_version >= 3) dip->di_v3_pad = 0; + +if (flags2 &XFS_DIFLAG2_METADATA ) { +xfs_failaddr_t fa; + + fa =xfs_dinode_verify_metadir (sc->mp, dip, mode, flags, + flags2); +if (fa) + flags2 &= ~XFS_DIFLAG2_METADATA ; + } + dip->di_flags =cpu_to_be16 (flags); dip->di_flags2 =cpu_to_be64 (flags2); }
fs/xfs/xfs_icache.c +10 -2
@@ -834,7 +834,8 @@ xfs_iget(/* * Get a metadata inode. * -* The metafile type must match the file mode exactly. +* The metafile type must match the file mode exactly, and for files in the +* metadata directory tree, it must match the inode's metatype exactly. */ int xfs_trans_metafile_iget(
@@ -863,13 +864,20 @@ xfs_trans_metafile_iget( mode =S_IFREG ;if (inode_wrong_type (VFS_I (ip), mode)) goto bad_rele; +if (xfs_has_metadir (mp)) { +if (!xfs_is_metadir_inode (ip)) + goto bad_rele; +if (metafile_type != ip->i_metatype) + goto bad_rele; + } *ipp = ip;return 0 ; bad_rele:xfs_irele (ip); whine: -xfs_err (mp,"metadata inode 0x%llx is corrupt" , ino); +xfs_err (mp,"metadata inode 0x%llx type %u is corrupt" , ino, + metafile_type);return -EFSCORRUPTED ; }
fs/xfs/xfs_inode.c +11 -0
@@ -555,8 +555,19 @@ xfs_lookup(if (error) goto out_free_name; +/* +* Fail if a directory entry in the regular directory tree points to +* a metadata file. +*/ +if (XFS_IS_CORRUPT (dp->i_mount,xfs_is_metadir_inode (*ipp))) { + error = -EFSCORRUPTED ; + goto out_irele; + } +return 0 ; +out_irele: +xfs_irele (*ipp); out_free_name:if (ci_name)kfree (ci_name->name);
PATCH 9/29 xfs: read and write metadata inode directory tree
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
Plumb in the bits we need to load metadata inodes from a named entry in a metadir directory, create (or hardlink) inodes into a metadir directory, create metadir directories, and flag inodes as being metadata files.
--- fs/xfs/Makefile | 4 fs/xfs/libxfs/xfs_metadir.c | 474 ++++++++++++++++++++++++++++++++++++++++++ fs/xfs/libxfs/xfs_metadir.h | 47 ++++ fs/xfs/libxfs/xfs_metafile.c | 52 +++++ fs/xfs/libxfs/xfs_metafile.h | 4 fs/xfs/xfs_icache.c | 2 fs/xfs/xfs_trace.c | 2 fs/xfs/xfs_trace.h | 102 +++++++++ 8 files changed, 685 insertions(+), 2 deletions(-) create mode 100644 fs/xfs/libxfs/xfs_metadir.c create mode 100644 fs/xfs/libxfs/xfs_metadir.h create mode 100644 fs/xfs/libxfs/xfs_metafile.c
fs/xfs/Makefile +3 -1
@@ -16,6 +16,7 @@ xfs-y += xfs_trace.o xfs-y += $(addprefix libxfs/, \ xfs_group.o \ xfs_ag.o \ + xfs_ag_resv.o \ xfs_alloc.o \ xfs_alloc_btree.o \ xfs_attr.o \
@@ -43,7 +44,8 @@ xfs-y += $(addprefix libxfs/, \ xfs_inode_buf.o \ xfs_inode_util.o \ xfs_log_rlimit.o \ - xfs_ag_resv.o \ + xfs_metadir.o \ + xfs_metafile.o \ xfs_parent.o \ xfs_rmap.o \ xfs_rmap_btree.o \
fs/xfs/libxfs/xfs_metadir.c new file +474 -0
474 lines not on this page · raw message
fs/xfs/libxfs/xfs_metadir.h new file +47 -0
47 lines not on this page · raw message
fs/xfs/libxfs/xfs_metafile.c new file +52 -0
52 lines not on this page · raw message
fs/xfs/libxfs/xfs_metafile.h +4 -0
@@ -17,6 +17,10 @@#define XFS_METADIR_DIFLAGS (XFS_METAFILE_DIFLAGS | \ XFS_DIFLAG_NOSYMLINKS) +void xfs_metafile_set_iflag (struct xfs_trans *tp,struct xfs_inode *ip, +enum xfs_metafile_type metafile_type); +void xfs_metafile_clear_iflag (struct xfs_trans *tp,struct xfs_inode *ip); +/* Code specific to kernel/userspace; must be provided externally. */ int xfs_trans_metafile_iget(struct xfs_trans *tp, xfs_ino_t ino,
fs/xfs/xfs_icache.c +1 -1
@@ -850,7 +850,7 @@ xfs_trans_metafile_iget(int error; error =xfs_iget (mp, tp, ino,0 ,0 , &ip); -if (error == -EFSCORRUPTED ) +if (error == -EFSCORRUPTED || error == -EINVAL ) goto whine;if (error)return error;
fs/xfs/xfs_trace.c +2 -0
@@ -46,6 +46,8 @@#include "xfs_parent.h" #include "xfs_rmap.h" #include "xfs_refcount.h" +#include "xfs_metafile.h" +#include "xfs_metadir.h" /* * We include this last to have the helpers above available for the trace
fs/xfs/xfs_trace.h +102 -0
114 lines not on this page · raw message
PATCH 10/29 xfs: disable the agi rotor for metadata inodes
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
Ideally, we'd put all the metadata inodes in one place if we could, so that the metadata all stay reasonably close together instead of spreading out over the disk. Furthermore, if the log is internal we'd probably prefer to keep the metadata near the log. Therefore, disable AGI rotoring for metadata inode allocations.
--- fs/xfs/libxfs/xfs_ialloc.c | 58 ++++++++++++++++++++++++++++++-------------- 1 file changed, 40 insertions(+), 18 deletions(-)
fs/xfs/libxfs/xfs_ialloc.c +40 -18
@@ -1841,6 +1841,40 @@ xfs_dialloc_try_ag(return error; } +/* +* Pick an AG for the new inode. +* +* Directories, symlinks, and regular files frequently allocate at least one +* block, so factor that potential expansion when we examine whether an AG has +* enough space for file creation. Try to keep metadata files all in the same +* AG. +*/ +static inline xfs_agnumber_t +xfs_dialloc_pick_ag ( +struct xfs_mount *mp, +struct xfs_inode *dp, +umode_t mode) +{ +xfs_agnumber_t start_agno; + +if (!dp) +return 0 ; +if (xfs_is_metadir_inode (dp)) { +if (mp->m_sb.sb_logstart) +return XFS_FSB_TO_AGNO (mp, mp->m_sb.sb_logstart); +return 0 ; + } + +if (S_ISDIR (mode)) +return (atomic_inc_return (&mp->m_agirotor) -1 ) % mp->m_maxagi; + + start_agno =XFS_INO_TO_AGNO (mp, dp->i_ino); +if (start_agno >= mp->m_maxagi) + start_agno =0 ; + +return start_agno; +} +/* * Allocate an on-disk inode. *
@@ -1856,31 +1890,19 @@ xfs_dialloc( xfs_ino_t *new_ino) {struct xfs_mount *mp = (*tpp)->t_mountp; +struct xfs_perag *pag; +struct xfs_ino_geometry *igeo =M_IGEO (mp); +xfs_ino_t ino =NULLFSINO ;xfs_ino_t parent = args->pip ? args->pip->i_ino :0 ; -umode_t mode = args->mode &S_IFMT ;xfs_agnumber_t agno; -int error =0 ;xfs_agnumber_t start_agno; -struct xfs_perag *pag; -struct xfs_ino_geometry *igeo =M_IGEO (mp); +umode_t mode = args->mode &S_IFMT ;bool ok_alloc = true;bool low_space = false;int flags; -xfs_ino_t ino =NULLFSINO ; +int error =0 ; -/* -* Directories, symlinks, and regular files frequently allocate at least -* one block, so factor that potential expansion when we examine whether -* an AG has enough space for file creation. -*/ -if (S_ISDIR (mode)) - start_agno = (atomic_inc_return (&mp->m_agirotor) -1 ) % - mp->m_maxagi; -else { - start_agno =XFS_INO_TO_AGNO (mp, parent); -if (start_agno >= mp->m_maxagi) - start_agno =0 ; - } + start_agno =xfs_dialloc_pick_ag (mp, args->pip, mode);/* * If we have already hit the ceiling of inode blocks then clear
PATCH 11/29 xfs: hide metadata inodes from everyone because they are special
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
Metadata inodes are private files and therefore cannot be exposed to userspace. This means no bulkstat, no open-by-handle, no linking them into the directory tree, and no feeding them to LSMs. As such, we mark them S_PRIVATE, which stops all that.
--- fs/xfs/scrub/tempfile.c | 8 ++++++++ fs/xfs/xfs_iops.c | 15 ++++++++++++++- 2 files changed, 22 insertions(+), 1 deletion(-)
fs/xfs/scrub/tempfile.c +8 -0
@@ -844,6 +844,14 @@ xrep_is_tempfile( const struct xfs_inode *ip) {const struct inode *inode = &ip->i_vnode; +struct xfs_mount *mp = ip->i_mount; + +/* +* Files in the metadata directory tree also have S_PRIVATE set and +* IOP_XATTR unset, so we must distinguish them separately. +*/ +if (xfs_has_metadir (mp) && (ip->i_diflags2 &XFS_DIFLAG2_METADATA )) +return false;if (IS_PRIVATE (inode) && !(inode->i_opflags &IOP_XATTR ))return true;
fs/xfs/xfs_iops.c +14 -1
@@ -42,7 +42,9 @@* held. For regular files, the lock order is the other way around - the * mmap_lock is taken during the page fault, and then we lock the ilock to do * block mapping. Hence we need a different class for the directory ilock so -* that lockdep can tell them apart. +* that lockdep can tell them apart. Directories in the metadata directory +* tree get a separate class so that lockdep reports will warn us if someone +* ever tries to lock regular directories after locking metadata directories. */ static struct lock_class_key xfs_nondir_ilock_class;static struct lock_class_key xfs_dir_ilock_class;
@@ -1289,6 +1291,7 @@ xfs_setup_inode( {struct inode *inode = &ip->i_vnode;gfp_t gfp_mask; +bool is_meta =xfs_is_internal_inode (ip); inode->i_ino = ip->i_ino; inode->i_state |=I_NEW ;
@@ -1300,6 +1303,16 @@ xfs_setup_inode(i_size_write (inode, ip->i_disk_size);xfs_diflags_to_iflags (ip, true); +/* +* Mark our metadata files as private so that LSMs and the ACL code +* don't try to add their own metadata or reason about these files, +* and users cannot ever obtain file handles to them. +*/ +if (is_meta) { + inode->i_flags |=S_PRIVATE ; + inode->i_opflags &= ~IOP_XATTR ; + } +if (S_ISDIR (inode->i_mode)) {/* * We set the i_rwsem class here to avoid potential races with
PATCH 12/29 xfs: advertise metadata directory feature
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
Advertise the existence of the metadata directory feature; this will be used by scrub to decide if it needs to scan the metadir too.
--- fs/xfs/libxfs/xfs_fs.h | 1 + fs/xfs/libxfs/xfs_sb.c | 2 ++ 2 files changed, 3 insertions(+)
fs/xfs/libxfs/xfs_fs.h +1 -0
@@ -242,6 +242,7 @@ typedef struct xfs_fsop_resblks {#define XFS_FSOP_GEOM_FLAGS_NREXT64 (1 << 23)/* large extent counters */ #define XFS_FSOP_GEOM_FLAGS_EXCHANGE_RANGE (1 << 24)/* exchange range */ #define XFS_FSOP_GEOM_FLAGS_PARENT (1 << 25)/* linux parent pointers */ +#define XFS_FSOP_GEOM_FLAGS_METADIR (1 << 26)/* metadata directories */ /* * Minimum and maximum sizes need for growth checks.
fs/xfs/libxfs/xfs_sb.c +2 -0
@@ -1295,6 +1295,8 @@ xfs_fs_geometry( geo->flags |=XFS_FSOP_GEOM_FLAGS_NREXT64 ;if (xfs_has_exchange_range (mp)) geo->flags |=XFS_FSOP_GEOM_FLAGS_EXCHANGE_RANGE ; +if (xfs_has_metadir (mp)) + geo->flags |=XFS_FSOP_GEOM_FLAGS_METADIR ; geo->rtsectsize = sbp->sb_blocksize; geo->dirblocksize =xfs_dir2_dirblock_bytes (sbp);
PATCH 13/29 xfs: allow bulkstat to return metadata directories
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
Allow the V5 bulkstat ioctl to return information about metadata directory files so that xfs_scrub can find and scrub them, since they are otherwise ordinary directories.
(Metadata files of course require per-file scrub code and hence do not need exposure.)
--- fs/xfs/libxfs/xfs_fs.h | 10 +++++++++- fs/xfs/xfs_ioctl.c | 7 +++++++ fs/xfs/xfs_itable.c | 33 +++++++++++++++++++++++++++++---- fs/xfs/xfs_itable.h | 3 +++ 4 files changed, 48 insertions(+), 5 deletions(-)
fs/xfs/libxfs/xfs_fs.h +9 -1
@@ -490,9 +490,17 @@ struct xfs_bulk_ireq {*/ #define XFS_BULK_IREQ_NREXT64 (1U << 2) +/* +* Allow bulkstat to return information about metadata directories. This +* enables xfs_scrub to find them for scanning, as they are otherwise ordinary +* directories. +*/ +#define XFS_BULK_IREQ_METADIR (1U << 3) +#define XFS_BULK_IREQ_FLAGS_ALL (XFS_BULK_IREQ_AGNO | \ XFS_BULK_IREQ_SPECIAL | \ - XFS_BULK_IREQ_NREXT64) + XFS_BULK_IREQ_NREXT64 | \ + XFS_BULK_IREQ_METADIR)/* Operate on the root directory inode. */ #define XFS_BULK_IREQ_SPECIAL_ROOT (1)
fs/xfs/xfs_ioctl.c +7 -0
@@ -233,6 +233,10 @@ xfs_bulk_ireq_setup(if (hdr->flags &XFS_BULK_IREQ_NREXT64 ) breq->flags |=XFS_IBULK_NREXT64 ; +/* Caller wants to see metadata directories in bulkstat output. */ +if (hdr->flags &XFS_BULK_IREQ_METADIR ) + breq->flags |=XFS_IBULK_METADIR ; +return 0 ; }
@@ -323,6 +327,9 @@ xfs_ioc_inumbers(if (copy_from_user (&hdr, &arg->hdr,sizeof (hdr)))return -EFAULT ; +if (hdr.flags &XFS_BULK_IREQ_METADIR ) +return -EINVAL ; + error =xfs_bulk_ireq_setup (mp, &hdr, &breq, arg->inumbers);if (error == -ECANCELED ) goto out_teardown;
fs/xfs/xfs_itable.c +29 -4
@@ -36,6 +36,14 @@ struct xfs_bstat_chunk {struct xfs_bulkstat *buf; }; +static inline bool +want_metadir_file ( +struct xfs_inode *ip, +struct xfs_ibulk *breq) +{ +return xfs_is_metadir_inode (ip) && (breq->flags &XFS_IBULK_METADIR ); +} +/* * Fill out the bulkstat info for a single inode and report it somewhere. *
@@ -69,9 +77,6 @@ xfs_bulkstat_one_int(vfsuid_t vfsuid;vfsgid_t vfsgid; -if (xfs_is_sb_inum (mp, ino)) - goto out_advance; - error =xfs_iget (mp, tp, ino, (XFS_IGET_DONTCACHE |XFS_IGET_UNTRUSTED ),XFS_ILOCK_SHARED , &ip);
@@ -97,8 +102,28 @@ xfs_bulkstat_one_int( vfsuid =i_uid_into_vfsuid (idmap, inode); vfsgid =i_gid_into_vfsgid (idmap, inode); +/* +* If caller wants files from the metadata directories, push out the +* bare minimum information for enabling scrub. +*/ +if (want_metadir_file (ip, bc->breq)) { +memset (buf,0 ,sizeof (*buf)); + buf->bs_ino = ino; + buf->bs_gen = inode->i_generation; + buf->bs_mode = inode->i_mode &S_IFMT ; +xfs_bulkstat_health (ip, buf); + buf->bs_version =XFS_BULKSTAT_VERSION_V5 ; +xfs_iunlock (ip,XFS_ILOCK_SHARED ); +xfs_irele (ip); + + error = bc->formatter (bc->breq, buf); +if (!error || error == -ECANCELED ) + goto out_advance; + goto out; + } +/* If this is a private inode, don't leak its details to userspace. */ -if (IS_PRIVATE (inode)) { +if (IS_PRIVATE (inode) ||xfs_is_sb_inum (mp, ino)) {xfs_iunlock (ip,XFS_ILOCK_SHARED );xfs_irele (ip); error = -EINVAL ;
fs/xfs/xfs_itable.h +3 -0
@@ -22,6 +22,9 @@ struct xfs_ibulk {/* Fill out the bs_extents64 field if set. */ #define XFS_IBULK_NREXT64 (1U << 1) +/* Signal that we can return metadata directories. */ +#define XFS_IBULK_METADIR (1U << 2) +/* * Advance the user buffer pointer by one record of the given size. If the * buffer is now full, return the appropriate error code.
PATCH 14/29 xfs: don't count metadata directory files to quota
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
Files in the metadata directory tree are internal to the filesystem. Don't count the inodes or the blocks they use in the root dquot because users do not need to know about their resource usage. This will also quiet down complaints about dquot usage not matching du output.
--- fs/xfs/xfs_dquot.c | 1 + fs/xfs/xfs_qm.c | 11 +++++++++++ fs/xfs/xfs_quota.h | 5 +++++ fs/xfs/xfs_trans_dquot.c | 6 ++++++ 4 files changed, 23 insertions(+)
fs/xfs/xfs_dquot.c +1 -0
@@ -983,6 +983,7 @@ xfs_qm_dqget_inode(xfs_assert_ilocked (ip,XFS_ILOCK_EXCL );ASSERT (xfs_inode_dquot (ip, type) ==NULL ); +ASSERT (!xfs_is_metadir_inode (ip)); id =xfs_qm_id_for_quotatype (ip, type);
fs/xfs/xfs_qm.c +11 -0
@@ -304,6 +304,8 @@ xfs_qm_need_dqattach(return false;if (xfs_is_quota_inode (&mp->m_sb, ip->i_ino))return false; +if (xfs_is_metadir_inode (ip)) +return false;return true; }
@@ -326,6 +328,7 @@ xfs_qm_dqattach_locked(return 0 ;xfs_assert_ilocked (ip,XFS_ILOCK_EXCL ); +ASSERT (!xfs_is_metadir_inode (ip));if (XFS_IS_UQUOTA_ON (mp) && !ip->i_udquot) { error = xfs_qm_dqattach_one(ip, XFS_DQTYPE_USER,
@@ -1204,6 +1207,10 @@ xfs_qm_dqusage_adjust( } } +/* Metadata directory files are not accounted to user-visible quotas. */ +if (xfs_is_metadir_inode (ip)) + goto error0; +ASSERT (ip->i_delayed_blks ==0 );if (XFS_IS_REALTIME_INODE (ip)) {
@@ -1754,6 +1761,8 @@ xfs_qm_vop_dqalloc(if (!XFS_IS_QUOTA_ON (mp))return 0 ; +ASSERT (!xfs_is_metadir_inode (ip)); + lockflags =XFS_ILOCK_EXCL ;xfs_ilock (ip, lockflags);
@@ -1883,6 +1892,7 @@ xfs_qm_vop_chown(xfs_assert_ilocked (ip,XFS_ILOCK_EXCL );ASSERT (XFS_IS_QUOTA_ON (ip->i_mount)); +ASSERT (!xfs_is_metadir_inode (ip));/* old dquot */ prevdq = *IO_olddq;
@@ -1970,6 +1980,7 @@ xfs_qm_vop_create_dqattach(return ;xfs_assert_ilocked (ip,XFS_ILOCK_EXCL ); +ASSERT (!xfs_is_metadir_inode (ip));if (udqp &&XFS_IS_UQUOTA_ON (mp)) {ASSERT (ip->i_udquot ==NULL );
fs/xfs/xfs_quota.h +5 -0
@@ -29,6 +29,11 @@ struct xfs_buf; (XFS_IS_GQUOTA_ON(mp) && (ip)->i_gdquot == NULL) || \ (XFS_IS_PQUOTA_ON(mp) && (ip)->i_pdquot == NULL)) +#define XFS_IS_DQDETACHED (ip) \ + ((ip)->i_udquot == NULL && \ + (ip)->i_gdquot == NULL && \ + (ip)->i_pdquot == NULL) +#define XFS_QM_NEED_QUOTACHECK (mp) \ ((XFS_IS_UQUOTA_ON(mp) && \ (mp->m_sb.sb_qflags & XFS_UQUOTA_CHKD) == 0) || \
fs/xfs/xfs_trans_dquot.c +6 -0
@@ -156,6 +156,8 @@ xfs_trans_mod_ino_dquot( unsigned int field, int64_t delta) { +ASSERT (!xfs_is_metadir_inode (ip) ||XFS_IS_DQDETACHED (ip)); +xfs_trans_mod_dquot (tp, dqp, field, delta);if (xfs_hooks_switched_on (&xfs_dqtrx_hooks_switch)) {
@@ -247,6 +249,8 @@ xfs_trans_mod_dquot_byino( xfs_is_quota_inode(&mp->m_sb, ip->i_ino)) return; +ASSERT (!xfs_is_metadir_inode (ip) ||XFS_IS_DQDETACHED (ip)); +if (XFS_IS_UQUOTA_ON (mp) && ip->i_udquot)xfs_trans_mod_ino_dquot (tp, ip, ip->i_udquot, field, delta);if (XFS_IS_GQUOTA_ON (mp) && ip->i_gdquot)
@@ -962,6 +966,8 @@ xfs_trans_reserve_quota_nblks(if (!XFS_IS_QUOTA_ON (mp))return 0 ; +if (xfs_is_metadir_inode (ip)) +return 0 ;ASSERT (!xfs_is_quota_inode (&mp->m_sb, ip->i_ino));xfs_assert_ilocked (ip,XFS_ILOCK_EXCL );
PATCH 15/29 xfs: mark quota inodes as metadata files
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
When we're creating quota files at mount time, make sure to mark them as metadir inodes if appropriate.
--- fs/xfs/xfs_qm.c | 2 ++ 1 file changed, 2 insertions(+)
fs/xfs/xfs_qm.c +2 -0
@@ -824,6 +824,8 @@ xfs_qm_qino_alloc(xfs_trans_cancel (tp);return error; } +if (xfs_has_metadir (mp)) +xfs_metafile_set_iflag (tp, *ipp, metafile_type); }/*
PATCH 16/29 xfs: adjust xfs_bmap_add_attrfork for metadir
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
Online repair might use the xfs_bmap_add_attrfork to repair a file in the metadata directory tree if (say) the metadata file lacks the correct parent pointers. In that case, it is not correct to check that the file is dqattached -- metadata files must be not have /any/ dquot attached at all. Adjust the assertions appropriately.
--- fs/xfs/libxfs/xfs_attr.c | 5 ++++- fs/xfs/libxfs/xfs_bmap.c | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-)
fs/xfs/libxfs/xfs_attr.c +4 -1
@@ -1004,7 +1004,10 @@ xfs_attr_add_fork(unsigned int blks;/* space reservation */ int error;/* error return value */ -ASSERT (!XFS_NOT_DQATTACHED (mp, ip)); +if (xfs_is_metadir_inode (ip)) +ASSERT (XFS_IS_DQDETACHED (ip)); +else +ASSERT (!XFS_NOT_DQATTACHED (mp, ip)); blks =XFS_ADDAFORK_SPACE_RES (mp);
fs/xfs/libxfs/xfs_bmap.c +4 -1
@@ -1042,7 +1042,10 @@ xfs_bmap_add_attrfork(int error;/* error return value */ xfs_assert_ilocked (ip,XFS_ILOCK_EXCL ); -ASSERT (!XFS_NOT_DQATTACHED (mp, ip)); +if (xfs_is_metadir_inode (ip)) +ASSERT (XFS_IS_DQDETACHED (ip)); +else +ASSERT (!XFS_NOT_DQATTACHED (mp, ip));ASSERT (!xfs_inode_has_attr_fork (ip));xfs_trans_log_inode (tp, ip,XFS_ILOG_CORE );
PATCH 17/29 xfs: record health problems with the metadata directory
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
Make a report to the health monitoring subsystem any time we encounter something in the metadata directory tree that looks like corruption.
--- fs/xfs/libxfs/xfs_fs.h | 1 + fs/xfs/libxfs/xfs_health.h | 4 +++- fs/xfs/libxfs/xfs_metadir.c | 13 ++++++++++--- fs/xfs/xfs_health.c | 1 + fs/xfs/xfs_icache.c | 1 + fs/xfs/xfs_inode.c | 1 + 6 files changed, 17 insertions(+), 4 deletions(-)
fs/xfs/libxfs/xfs_fs.h +1 -0
@@ -198,6 +198,7 @@ struct xfs_fsop_geom {#define XFS_FSOP_GEOM_SICK_RT_SUMMARY (1 << 5)/* realtime summary */ #define XFS_FSOP_GEOM_SICK_QUOTACHECK (1 << 6)/* quota counts */ #define XFS_FSOP_GEOM_SICK_NLINKS (1 << 7)/* inode link counts */ +#define XFS_FSOP_GEOM_SICK_METADIR (1 << 8)/* metadata directory */ /* Output for XFS_FS_COUNTS */ typedef struct xfs_fsop_counts {
fs/xfs/libxfs/xfs_health.h +3 -1
@@ -62,6 +62,7 @@ struct xfs_da_args;#define XFS_SICK_FS_PQUOTA (1 << 3)/* project quota */ #define XFS_SICK_FS_QUOTACHECK (1 << 4)/* quota counts */ #define XFS_SICK_FS_NLINKS (1 << 5)/* inode link counts */ +#define XFS_SICK_FS_METADIR (1 << 6)/* metadata directory tree */ /* Observable health issues for realtime volume metadata. */ #define XFS_SICK_RT_BITMAP (1 << 0)/* realtime bitmap */
@@ -105,7 +106,8 @@ struct xfs_da_args;XFS_SICK_FS_GQUOTA | \XFS_SICK_FS_PQUOTA | \XFS_SICK_FS_QUOTACHECK | \ - XFS_SICK_FS_NLINKS) +XFS_SICK_FS_NLINKS | \ + XFS_SICK_FS_METADIR) #define XFS_SICK_RT_PRIMARY (XFS_SICK_RT_BITMAP | \XFS_SICK_RT_SUMMARY )
fs/xfs/libxfs/xfs_metadir.c +10 -3
@@ -28,6 +28,7 @@#include "xfs_dir2.h" #include "xfs_dir2_priv.h" #include "xfs_parent.h" +#include "xfs_health.h" /* * Metadata Directory Tree
@@ -94,8 +95,10 @@ xfs_metadir_lookup( };int error; -if (!S_ISDIR (VFS_I (dp)->i_mode)) +if (!S_ISDIR (VFS_I (dp)->i_mode)) { +xfs_fs_mark_sick (mp,XFS_SICK_FS_METADIR );return -EFSCORRUPTED ; + }if (xfs_is_shutdown (mp))return -EIO ;
@@ -103,10 +106,14 @@ xfs_metadir_lookup(if (error)return error; -if (!xfs_verify_ino (mp, args.inumber)) +if (!xfs_verify_ino (mp, args.inumber)) { +xfs_fs_mark_sick (mp,XFS_SICK_FS_METADIR );return -EFSCORRUPTED ; -if (xname->type !=XFS_DIR3_FT_UNKNOWN && xname->type != args.filetype) + } +if (xname->type !=XFS_DIR3_FT_UNKNOWN && xname->type != args.filetype) { +xfs_fs_mark_sick (mp,XFS_SICK_FS_METADIR );return -EFSCORRUPTED ; + }trace_xfs_metadir_lookup (dp, xname, args.inumber); *ino = args.inumber;
fs/xfs/xfs_health.c +1 -0
@@ -380,6 +380,7 @@ static const struct ioctl_sick_map fs_map[] = { { XFS_SICK_FS_PQUOTA, XFS_FSOP_GEOM_SICK_PQUOTA }, { XFS_SICK_FS_QUOTACHECK, XFS_FSOP_GEOM_SICK_QUOTACHECK }, { XFS_SICK_FS_NLINKS, XFS_FSOP_GEOM_SICK_NLINKS }, + { XFS_SICK_FS_METADIR, XFS_FSOP_GEOM_SICK_METADIR }, { 0, 0 }, };
fs/xfs/xfs_icache.c +1 -0
@@ -878,6 +878,7 @@ xfs_trans_metafile_iget( whine:xfs_err (mp,"metadata inode 0x%llx type %u is corrupt" , ino, metafile_type); +xfs_fs_mark_sick (mp,XFS_SICK_FS_METADIR );return -EFSCORRUPTED ; }
fs/xfs/xfs_inode.c +1 -0
@@ -560,6 +560,7 @@ xfs_lookup(* a metadata file. */ if (XFS_IS_CORRUPT (dp->i_mount,xfs_is_metadir_inode (*ipp))) { +xfs_fs_mark_sick (dp->i_mount,XFS_SICK_FS_METADIR ); error = -EFSCORRUPTED ; goto out_irele; }
PATCH 18/29 xfs: refactor directory tree root predicates
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
Metadata directory trees make reasoning about the parent of a file more difficult. Traditionally, user files are children of sb_rootino, and metadata files are "children" of the superblock. Now, we add a third possibility -- some metadata files can be children of sb_metadirino, but the classic ones (rt free space data and quotas) are left alone.
Let's add some helper functions (instead of open-coding the logic everywhere) to make scrub logic easier to understand.
--- fs/xfs/scrub/common.c | 29 +++++++++++++++++++++++++++++ fs/xfs/scrub/common.h | 4 ++++ fs/xfs/scrub/dir.c | 2 +- fs/xfs/scrub/dir_repair.c | 2 +- fs/xfs/scrub/dirtree.c | 15 ++++++++++++++- fs/xfs/scrub/dirtree.h | 12 +----------- fs/xfs/scrub/findparent.c | 15 +++++++++------ fs/xfs/scrub/inode_repair.c | 11 ++--------- fs/xfs/scrub/nlinks.c | 4 ++-- fs/xfs/scrub/nlinks_repair.c | 4 +--- fs/xfs/scrub/orphanage.c | 4 +++- fs/xfs/scrub/parent.c | 17 ++++++++--------- fs/xfs/scrub/parent_repair.c | 2 +- 13 files changed, 76 insertions(+), 45 deletions(-)
fs/xfs/scrub/common.c +29 -0
@@ -1452,3 +1452,32 @@ xchk_inode_is_allocated(rcu_read_unlock ();return error; } + +/* Is this inode a root directory for either tree? */ +bool +xchk_inode_is_dirtree_root (const struct xfs_inode *ip) +{ +struct xfs_mount *mp = ip->i_mount; + +return ip == mp->m_rootip || + (xfs_has_metadir (mp) && ip == mp->m_metadirip); +} + +/* Does the superblock point down to this inode? */ +bool +xchk_inode_is_sb_rooted (const struct xfs_inode *ip) +{ +return xchk_inode_is_dirtree_root (ip) || +xfs_is_sb_inum (ip->i_mount, ip->i_ino); +} + +/* What is the root directory inumber for this inode? */ +xfs_ino_t +xchk_inode_rootdir_inum (const struct xfs_inode *ip) +{ +struct xfs_mount *mp = ip->i_mount; + +if (xfs_is_metadir_inode (ip)) +return mp->m_metadirip->i_ino; +return mp->m_rootip->i_ino; +}
fs/xfs/scrub/common.h +4 -0
@@ -242,4 +242,8 @@ void xchk_fsgates_enable(struct xfs_scrub *sc, unsigned int scrub_fshooks);int xchk_inode_is_allocated (struct xfs_scrub *sc,xfs_agino_t agino,bool *inuse); +bool xchk_inode_is_dirtree_root (const struct xfs_inode *ip); +bool xchk_inode_is_sb_rooted (const struct xfs_inode *ip); +xfs_ino_t xchk_inode_rootdir_inum (const struct xfs_inode *ip); +#endif /* __XFS_SCRUB_COMMON_H__ */
fs/xfs/scrub/dir.c +1 -1
@@ -253,7 +253,7 @@ xchk_dir_actor(* If this is ".." in the root inode, check that the inum * matches this dir. */ -if (dp->i_ino == mp->m_sb.sb_rootino && ino != dp->i_ino) +if (xchk_inode_is_dirtree_root (dp) && ino != dp->i_ino)xchk_fblock_set_corrupt (sc,XFS_DATA_FORK , offset); }
fs/xfs/scrub/dir_repair.c +1 -1
@@ -1270,7 +1270,7 @@ xrep_dir_scan_dirtree(int error;/* Roots of directory trees are their own parents. */ -if (sc->ip == sc->mp->m_rootip) +if (xchk_inode_is_dirtree_root (sc->ip))xrep_findparent_scan_found (&rd->pscan, sc->ip->i_ino);/*
fs/xfs/scrub/dirtree.c +14 -1
@@ -917,7 +917,7 @@ xchk_dirtree(* scan, because the hook doesn't detach until after sc->ip gets * released during teardown. */ - dl->root_ino = sc->mp->m_rootip->i_ino; + dl->root_ino =xchk_inode_rootdir_inum (sc->ip); dl->scan_ino = sc->ip->i_ino;trace_xchk_dirtree_start (sc->ip, sc->sm,0 );
@@ -983,3 +983,16 @@ xchk_dirtree(trace_xchk_dirtree_done (sc->ip, sc->sm, error);return error; } + +/* Does the directory targetted by this scrub have no parents? */ +bool +xchk_dirtree_parentless (const struct xchk_dirtree *dl) +{ +struct xfs_scrub *sc = dl->sc; + +if (xchk_inode_is_dirtree_root (sc->ip)) +return true; +if (VFS_I (sc->ip)->i_nlink ==0 ) +return true; +return false; +}
fs/xfs/scrub/dirtree.h +1 -11
@@ -156,17 +156,7 @@ struct xchk_dirtree {#define xchk_dirtree_for_each_path (dl, path) \ list_for_each_entry((path), &(dl)->path_list, list) -static inline bool -xchk_dirtree_parentless (const struct xchk_dirtree *dl) -{ -struct xfs_scrub *sc = dl->sc; - -if (sc->ip == sc->mp->m_rootip) -return true; -if (VFS_I (sc->ip)->i_nlink ==0 ) -return true; -return false; -} +bool xchk_dirtree_parentless (const struct xchk_dirtree *dl);int xchk_dirtree_find_paths_to_root (struct xchk_dirtree *dl); int xchk_dirpath_append(struct xchk_dirtree *dl, struct xfs_inode *ip,
fs/xfs/scrub/findparent.c +9 -6
@@ -362,15 +362,18 @@ xrep_findparent_confirm( };int error; -/* -* The root directory always points to itself. Unlinked dirs can point -* anywhere, so we point them at the root dir too. -*/ -if (sc->ip == sc->mp->m_rootip ||VFS_I (sc->ip)->i_nlink ==0 ) { +/* The root directory always points to itself. */ +if (sc->ip == sc->mp->m_rootip) { *parent_ino = sc->mp->m_sb.sb_rootino;return 0 ; } +/* Unlinked dirs can point anywhere; point them up to the root dir. */ +if (VFS_I (sc->ip)->i_nlink ==0 ) { + *parent_ino =xchk_inode_rootdir_inum (sc->ip); +return 0 ; + } +/* Reject garbage parent inode numbers and self-referential parents. */ if (*parent_ino ==NULLFSINO )return 0 ;
@@ -413,7 +416,7 @@ xrep_findparent_self_reference(return sc->mp->m_sb.sb_rootino;if (VFS_I (sc->ip)->i_nlink ==0 ) -return sc->mp->m_sb.sb_rootino; +return xchk_inode_rootdir_inum (sc->ip);return NULLFSINO ; }
fs/xfs/scrub/inode_repair.c +2 -9
@@ -1767,15 +1767,8 @@ xrep_inode_pptr(if (inode->i_nlink ==0 && !(inode->i_state &I_LINKABLE ))return 0 ; -/* The root directory doesn't have a parent pointer. */ -if (ip == mp->m_rootip) -return 0 ; - -/* -* Metadata inodes are rooted in the superblock and do not have any -* parents. -*/ -if (xfs_is_internal_inode (ip)) +/* Children of the superblock do not have parent pointers. */ +if (xchk_inode_is_sb_rooted (ip))return 0 ;/* Inode already has an attr fork; no further work possible here. */
fs/xfs/scrub/nlinks.c +2 -2
@@ -279,7 +279,7 @@ xchk_nlinks_collect_dirent(* determine the backref count. */ if (dotdot) { -if (dp == sc->mp->m_rootip) +if (xchk_inode_is_dirtree_root (dp)) error =xchk_nlinks_update_incore (xnc, ino,1 ,0 ,0 );else if (!xfs_has_parent (sc->mp)) error =xchk_nlinks_update_incore (xnc, ino,0 ,1 ,0 );
@@ -735,7 +735,7 @@ xchk_nlinks_compare_inode( } } -if (ip == sc->mp->m_rootip) { +if (xchk_inode_is_dirtree_root (ip)) {/* * For the root of a directory tree, both the '.' and '..' * entries should point to the root directory. The dotdot
fs/xfs/scrub/nlinks_repair.c +1 -3
@@ -60,11 +60,9 @@ xrep_nlinks_is_orphaned( unsigned int actual_nlink, const struct xchk_nlink *obs) { - struct xfs_mount *mp = ip->i_mount; -if (obs->parents !=0 )return false; -if (ip == mp->m_rootip || ip == sc->orphanage) +if (xchk_inode_is_dirtree_root (ip) || ip == sc->orphanage)return false;return actual_nlink !=0 ; }
fs/xfs/scrub/orphanage.c +3 -1
@@ -295,7 +295,9 @@ xrep_orphanage_can_adopt(return false;if (sc->ip == sc->orphanage)return false; -if (xfs_is_sb_inum (sc->mp, sc->ip->i_ino)) +if (xchk_inode_is_sb_rooted (sc->ip)) +return false; +if (xfs_is_internal_inode (sc->ip))return false;return true; }
fs/xfs/scrub/parent.c +8 -9
@@ -300,7 +300,7 @@ xchk_parent_pptr_and_dotdot( }/* Is this the root dir? Then '..' must point to itself. */ -if (sc->ip == sc->mp->m_rootip) { +if (xchk_inode_is_dirtree_root (sc->ip)) {if (sc->ip->i_ino != pp->parent_ino)xchk_fblock_set_corrupt (sc,XFS_DATA_FORK ,0 );return 0 ;
@@ -711,7 +711,7 @@ xchk_parent_count_pptrs( }if (S_ISDIR (VFS_I (sc->ip)->i_mode)) { -if (sc->ip == sc->mp->m_rootip) +if (xchk_inode_is_dirtree_root (sc->ip)) pp->pptrs_found++;if (VFS_I (sc->ip)->i_nlink ==0 && pp->pptrs_found >0 )
@@ -885,10 +885,9 @@ boolxchk_pptr_looks_zapped ( struct xfs_inode *ip) { -struct xfs_mount *mp = ip->i_mount;struct inode *inode =VFS_I (ip); -ASSERT (xfs_has_parent (mp)); +ASSERT (xfs_has_parent (ip->i_mount));/* * Temporary files that cannot be linked into the directory tree do not
@@ -902,15 +901,15 @@ xchk_pptr_looks_zapped(* of a parent pointer scan is always the empty set. It's safe to scan * them even if the attr fork was zapped. */ -if (ip == mp->m_rootip) +if (xchk_inode_is_dirtree_root (ip))return false;/* -* Metadata inodes are all rooted in the superblock and do not have -* any parents. Hence the attr fork will not be initialized, but -* there are no parent pointers that might have been zapped. +* Metadata inodes that are rooted in the superblock do not have any +* parents. Hence the attr fork will not be initialized, but there are +* no parent pointers that might have been zapped. */ -if (xfs_is_internal_inode (ip)) +if (xchk_inode_is_sb_rooted (ip))return false;/*
fs/xfs/scrub/parent_repair.c +1 -1
@@ -1334,7 +1334,7 @@ xrep_parent_rebuild_pptrs(* so that we can decide if we're moving this file to the orphanage. * For this purpose, root directories are their own parents. */ -if (sc->ip == sc->mp->m_rootip) { +if (xchk_inode_is_dirtree_root (sc->ip)) {xrep_findparent_scan_found (&rp->pscan, sc->ip->i_ino); }else { error =xrep_parent_lookup_pptrs (sc, &parent_ino);
PATCH 19/29 xfs: do not count metadata directory files when doing online quotacheck
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
Previously, we stated that files in the metadata directory tree are not counted in the dquot information. Fix the online quotacheck code to reflect this.
--- fs/xfs/scrub/quotacheck.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-)
fs/xfs/scrub/quotacheck.c +5 -2
@@ -398,10 +398,13 @@ xqcheck_collect_inode(bool isreg =S_ISREG (VFS_I (ip)->i_mode);int error =0 ; -if (xfs_is_quota_inode (&tp->t_mountp->m_sb, ip->i_ino)) { +if (xfs_is_metadir_inode (ip) || +xfs_is_quota_inode (&tp->t_mountp->m_sb, ip->i_ino)) {/* * Quota files are never counted towards quota, so we do not -* need to take the lock. +* need to take the lock. Files do not switch between the +* metadata and regular directory trees without a reallocation, +* so we do not need to ILOCK them either. */ xchk_iscan_mark_visited (&xqc->iscan, ip);return 0 ;
PATCH 20/29 xfs: don't fail repairs on metadata files with no attr fork
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
Fix a minor bug where we fail repairs on metadata files that do not have attr forks because xrep_metadata_inode_subtype doesn't filter ENOENT.
--- fs/xfs/scrub/repair.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
fs/xfs/scrub/repair.c +5 -3
@@ -1083,9 +1083,11 @@ xrep_metadata_inode_forks(return error;/* Make sure the attr fork looks ok before we delete it. */ - error =xrep_metadata_inode_subtype (sc,XFS_SCRUB_TYPE_BMBTA ); -if (error) -return error; +if (xfs_inode_hasattr (sc->ip)) { + error =xrep_metadata_inode_subtype (sc,XFS_SCRUB_TYPE_BMBTA ); +if (error) +return error; + }/* Clear the reflink flag since metadata never shares. */ if (xfs_is_reflink_inode (sc->ip)) {
Greg KH
maintainerRe: [PATCH 20/29] xfs: don't fail repairs on metadata files with no attr fork
Quoted 5 lines · Darrick J. Wong
From: Darrick J. Wong <[email protected]>
Fix a minor bug where we fail repairs on metadata files that do not have attr forks because
xrep_metadata_inode_subtypedoesn't filter ENOENT.
Quoted 7 lines
Cc <[email protected]> # v6.8Fixes 5a8e07e799721b ("xfs: repair the inode core and forks of a metadata inode")Signed-off-by Darrick J. Wong <[email protected]>Reviewed-by Christoph Hellwig <[email protected]>--- fs/xfs/scrub/repair.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
Why is a bugfix / stable-tagged-patch, number 20 in a 29 patch series? Why isn't it first, or better yet, on it's own if it is fixing a bug that people want merged "soon"?
thanks,
greg k-h
Re: [PATCH 20/29] xfs: don't fail repairs on metadata files with no attr fork
Quoted 14 lines · Greg KH
Quoted 5 lines · Darrick J. Wong
From: Darrick J. Wong <[email protected]>
Fix a minor bug where we fail repairs on metadata files that do not have attr forks because
xrep_metadata_inode_subtypedoesn't filter ENOENT.Quoted 7 lines
Cc <[email protected]> # v6.8Fixes 5a8e07e799721b ("xfs: repair the inode core and forks of a metadata inode")Signed-off-by Darrick J. Wong <[email protected]>Reviewed-by Christoph Hellwig <[email protected]>--- fs/xfs/scrub/repair.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
Quoted 3 lines
Why is a bugfix / stable-tagged-patch, number 20 in a 29 patch series? Why isn't it first, or better yet, on it's own if it is fixing a bug that people want merged "soon"?
I have too many patches, and every time I try to get a set through the review process I end up having to write *more* patches to appease the reviewers, and fixes get lost. Look at the copyrights on the other patches, I've been trying to get this upstreamed since 2018.
This particular bugfix got lost last month probably because I forgot to ping cem to take it for 6.12-rc1. Thanks for pushing on this, Greg.
Hey Carlos, can you queue this one up for 6.12-rc5, please?
--D
Quoted 4 lines
thanks,
greg k-h
Carlos Maiolino
maintainerRe: [PATCH 20/29] xfs: don't fail repairs on metadata files with no attr fork
Quoted 24 lines · Darrick J. Wong
Quoted 14 lines · Greg KH
Quoted 5 lines · Darrick J. Wong
From: Darrick J. Wong <[email protected]>
Fix a minor bug where we fail repairs on metadata files that do not have attr forks because
xrep_metadata_inode_subtypedoesn't filter ENOENT.Quoted 7 lines
Cc <[email protected]> # v6.8Fixes 5a8e07e799721b ("xfs: repair the inode core and forks of a metadata inode")Signed-off-by Darrick J. Wong <[email protected]>Reviewed-by Christoph Hellwig <[email protected]>--- fs/xfs/scrub/repair.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)Quoted 3 lines
Why is a bugfix / stable-tagged-patch, number 20 in a 29 patch series? Why isn't it first, or better yet, on it's own if it is fixing a bug that people want merged "soon"?
I have too many patches, and every time I try to get a set through the review process I end up having to write *more* patches to appease the reviewers, and fixes get lost. Look at the copyrights on the other patches, I've been trying to get this upstreamed since 2018.
Quoted 4 lines
This particular bugfix got lost last month probably because I forgot to ping cem to take it for 6.12-rc1. Thanks for pushing on this, Greg.
Hey Carlos, can you queue this one up for 6.12-rc5, please?
Sure, it's queued now in next-rc, I'm testing it and I hope to send it to for-next today yet. It's the only patch for -rc5.
Cheers.
Carlos
Quoted 8 lines
--D
Quoted 4 lines
thanks,
greg k-h
Re: [PATCH 20/29] xfs: don't fail repairs on metadata files with no attr fork
In reply to Darrick J. WongQuoted 4 lines · Darrick J. Wong
Fix a minor bug where we fail repairs on metadata files that do not have attr forks because
xrep_metadata_inode_subtypedoesn't filter ENOENT.
Applied to for-next, thanks!
[20/29] xfs: don't fail repairs on metadata files with no attr fork
commit: af8512c5277d17aae09be5305daa9118d2fa8881
Best regards,
Signature · 1 line
Carlos Maiolino <[email protected]>
PATCH 21/29 xfs: metadata files can have xattrs if metadir is enabled
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
If parent pointers are enabled, then metadata files will store parent pointers in xattrs, just like files in the user visible directory tree. Therefore, scrub and repair need to handle attr forks for metadata files on metadir filesystems.
--- fs/xfs/scrub/common.c | 21 +++++++++++++++------ fs/xfs/scrub/repair.c | 14 +++++++++++--- 2 files changed, 26 insertions(+), 9 deletions(-)
fs/xfs/scrub/common.c +15 -6
@@ -1245,12 +1245,6 @@ xchk_metadata_inode_forks(return 0 ; } -/* They also should never have extended attributes. */ -if (xfs_inode_hasattr (sc->ip)) { -xchk_ino_set_corrupt (sc, sc->ip->i_ino); -return 0 ; - } -/* Invoke the data fork scrubber. */ error =xchk_metadata_inode_subtype (sc,XFS_SCRUB_TYPE_BMBTD );if (error || (sc->sm->sm_flags &XFS_SCRUB_OFLAG_CORRUPT ))
@@ -1267,6 +1261,21 @@ xchk_metadata_inode_forks(xchk_ino_set_corrupt (sc, sc->ip->i_ino); } +/* +* Metadata files can only have extended attributes on metadir +* filesystems, either for parent pointers or for actual xattr data. +*/ +if (xfs_inode_hasattr (sc->ip)) { +if (!xfs_has_metadir (sc->mp)) { +xchk_ino_set_corrupt (sc, sc->ip->i_ino); +return 0 ; + } + + error =xchk_metadata_inode_subtype (sc,XFS_SCRUB_TYPE_BMBTA ); +if (error || (sc->sm->sm_flags &XFS_SCRUB_OFLAG_CORRUPT )) +return error; + } +return 0 ; }
fs/xfs/scrub/repair.c +11 -3
@@ -1082,7 +1082,12 @@ xrep_metadata_inode_forks(if (error)return error; -/* Make sure the attr fork looks ok before we delete it. */ +/* +* Metadata files can only have extended attributes on metadir +* filesystems, either for parent pointers or for actual xattr data. +* For a non-metadir filesystem, make sure the attr fork looks ok +* before we delete it. +*/ if (xfs_inode_hasattr (sc->ip)) { error =xrep_metadata_inode_subtype (sc,XFS_SCRUB_TYPE_BMBTA );if (error)
@@ -1098,8 +1103,11 @@ xrep_metadata_inode_forks(return error; } -/* Clear the attr forks since metadata shouldn't have that. */ -if (xfs_inode_hasattr (sc->ip)) { +/* +* Metadata files on non-metadir filesystems cannot have attr forks, +* so clear them now. +*/ +if (xfs_inode_hasattr (sc->ip) && !xfs_has_metadir (sc->mp)) {if (!dirty) { dirty = true;xfs_trans_ijoin (sc->tp, sc->ip,0 );
PATCH 22/29 xfs: adjust parent pointer scrubber for sb-rooted metadata files
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
Starting with the metadata directory feature, we're allowed to call the directory and parent pointer scrubbers for every metadata file, including the ones that are children of the superblock.
For these children, checking the link count against the number of parent pointers is a bit funny -- there's no such thing as a parent pointer for a child of the superblock since there's no corresponding dirent. For purposes of validating nlink, we pretend that there is a parent pointer.
--- fs/xfs/scrub/parent.c | 8 ++++++++ fs/xfs/scrub/parent_repair.c | 35 +++++++++++++++++++++++++++++++---- 2 files changed, 39 insertions(+), 4 deletions(-)
fs/xfs/scrub/parent.c +8 -0
@@ -720,6 +720,14 @@ xchk_parent_count_pptrs( pp->pptrs_found == 0)xchk_ino_set_corrupt (sc, sc->ip->i_ino); }else { +/* +* Starting with metadir, we allow checking of parent pointers +* of non-directory files that are children of the superblock. +* Pretend that we found a parent pointer attr. +*/ +if (xfs_has_metadir (sc->mp) &&xchk_inode_is_sb_rooted (sc->ip)) + pp->pptrs_found++; +if (VFS_I (sc->ip)->i_nlink != pp->pptrs_found)xchk_ino_set_corrupt (sc, sc->ip->i_ino); }
fs/xfs/scrub/parent_repair.c +31 -4
@@ -1354,21 +1354,40 @@ STATIC intxrep_parent_rebuild_tree ( struct xrep_parent *rp) { +struct xfs_scrub *sc = rp->sc; +bool try_adoption;int error; -if (xfs_has_parent (rp->sc->mp)) { +if (xfs_has_parent (sc->mp)) { error =xrep_parent_rebuild_pptrs (rp);if (error)return error; } -if (rp->pscan.parent_ino ==NULLFSINO ) { -if (xrep_orphanage_can_adopt (rp->sc)) +/* +* Any file with no parent could be adopted. This check happens after +* rebuilding the parent pointer structure because we might have cycled +* the ILOCK during that process. +*/ + try_adoption = rp->pscan.parent_ino ==NULLFSINO ; + +/* +* Starting with metadir, we allow checking of parent pointers +* of non-directory files that are children of the superblock. +* Lack of parent is ok here. +*/ +if (try_adoption &&xfs_has_metadir (sc->mp) && +xchk_inode_is_sb_rooted (sc->ip)) + try_adoption = false; + +if (try_adoption) { +if (xrep_orphanage_can_adopt (sc))return xrep_parent_move_to_orphanage (rp);return -EFSCORRUPTED ; + } -if (S_ISDIR (VFS_I (rp->sc->ip)->i_mode)) +if (S_ISDIR (VFS_I (sc->ip)->i_mode))return xrep_parent_reset_dotdot (rp);return 0 ;
@@ -1422,6 +1441,14 @@ xrep_parent_set_nondir_nlink(if (error)return error; +/* +* Starting with metadir, we allow checking of parent pointers of +* non-directory files that are children of the superblock. Pretend +* that we found a parent pointer attr. +*/ +if (xfs_has_metadir (sc->mp) &&xchk_inode_is_sb_rooted (sc->ip)) + rp->parents++; +if (rp->parents >0 &&xfs_inode_on_unlinked_list (ip)) {xfs_trans_ijoin (sc->tp, sc->ip,0 ); joined = true;
PATCH 23/29 xfs: fix di_metatype field of inodes that won't load
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
Make sure that the di_metatype field is at least set plausibly so that later scrubbers could set the real type.
--- fs/xfs/scrub/inode.c | 9 +++++++-- fs/xfs/scrub/inode_repair.c | 6 +++++- 2 files changed, 12 insertions(+), 3 deletions(-)
fs/xfs/scrub/inode.c +7 -2
@@ -443,8 +443,13 @@ xchk_dinode(break ;case 2 :case 3 : -if (!xfs_dinode_is_metadir (dip) && dip->di_metatype) -xchk_ino_set_corrupt (sc, ino); +if (xfs_dinode_is_metadir (dip)) { +if (be16_to_cpu (dip->di_metatype) >=XFS_METAFILE_MAX ) +xchk_ino_set_corrupt (sc, ino); + }else { +if (dip->di_metatype !=0 ) +xchk_ino_set_corrupt (sc, ino); + }if (dip->di_mode ==0 && sc->ip)xchk_ino_set_corrupt (sc, ino);
fs/xfs/scrub/inode_repair.c +5 -1
@@ -526,8 +526,12 @@ xrep_dinode_nlinks(return ; } -if (!xfs_dinode_is_metadir (dip)) +if (xfs_dinode_is_metadir (dip)) { +if (be16_to_cpu (dip->di_metatype) >=XFS_METAFILE_MAX ) + dip->di_metatype =cpu_to_be16 (XFS_METAFILE_UNKNOWN ); + }else { dip->di_metatype =0 ; + } }/* Fix any conflicting flags that the verifiers complain about. */
PATCH 24/29 xfs: scrub metadata directories
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
Teach online scrub about the metadata directory tree.
--- fs/xfs/scrub/dir.c | 8 ++++++++ fs/xfs/scrub/dir_repair.c | 6 ++++++ fs/xfs/scrub/dirtree.c | 17 ++++++++++++++--- fs/xfs/scrub/findparent.c | 13 +++++++++++++ fs/xfs/scrub/parent.c | 14 ++++++++++++++ fs/xfs/scrub/trace.h | 1 + 6 files changed, 56 insertions(+), 3 deletions(-)
fs/xfs/scrub/dir.c +8 -0
@@ -100,6 +100,14 @@ xchk_dir_check_ftype(if (xfs_mode_to_ftype (VFS_I (ip)->i_mode) != ftype)xchk_fblock_set_corrupt (sc,XFS_DATA_FORK , offset); + +/* +* Metadata and regular inodes cannot cross trees. This property +* cannot change without a full inode free and realloc cycle, so it's +* safe to check this without holding locks. +*/ +if (xfs_is_metadir_inode (ip) !=xfs_is_metadir_inode (sc->ip)) +xchk_fblock_set_corrupt (sc,XFS_DATA_FORK , offset); }/*
fs/xfs/scrub/dir_repair.c +6 -0
@@ -415,6 +415,12 @@ xrep_dir_salvage_entry(if (error)return 0 ; +/* Don't mix metadata and regular directory trees. */ +if (xfs_is_metadir_inode (ip) !=xfs_is_metadir_inode (rd->sc->ip)) { +xchk_irele (sc, ip); +return 0 ; + } + xname.type =xfs_mode_to_ftype (VFS_I (ip)->i_mode);xchk_irele (sc, ip);
fs/xfs/scrub/dirtree.c +14 -3
@@ -362,7 +362,8 @@ xchk_dirpath_set_outcome( STATIC intxchk_dirpath_step_up (struct xchk_dirtree *dl, -struct xchk_dirpath *path) +struct xchk_dirpath *path, +bool is_metadir) {struct xfs_scrub *sc = dl->sc;struct xfs_inode *dp;
@@ -435,6 +436,14 @@ xchk_dirpath_step_up( goto out_scanlock; } +/* Parent must be in the same directory tree. */ +if (is_metadir !=xfs_is_metadir_inode (dp)) { +trace_xchk_dirpath_crosses_tree (dl->sc, dp, path->path_nr, + path->nr_steps, &dl->xname, &dl->pptr_rec); + error = -EFSCORRUPTED ; + goto out_scanlock; + } +/* * If the extended attributes look as though they has been zapped by * the inode record repair code, we cannot scan for parent pointers.
@@ -508,6 +517,7 @@ xchk_dirpath_walk_upwards( struct xchk_dirpath *path) {struct xfs_scrub *sc = dl->sc; +bool is_metadir;int error;ASSERT (sc->ilock_flags &XFS_ILOCK_EXCL );
@@ -538,6 +548,7 @@ xchk_dirpath_walk_upwards(* ILOCK state is no longer tracked in the scrub context. Hence we * must drop @sc->ip's ILOCK during the walk. */ + is_metadir =xfs_is_metadir_inode (sc->ip);mutex_unlock (&dl->lock);xchk_iunlock (sc,XFS_ILOCK_EXCL );
@@ -547,7 +558,7 @@ xchk_dirpath_walk_upwards(* If we see any kind of error here (including corruptions), the parent * pointer of @sc->ip is corrupt. Stop the whole scan. */ - error =xchk_dirpath_step_up (dl, path); + error =xchk_dirpath_step_up (dl, path, is_metadir);if (error) {xchk_ilock (sc,XFS_ILOCK_EXCL );mutex_lock (&dl->lock);
@@ -560,7 +571,7 @@ xchk_dirpath_walk_upwards(* *somewhere* in the path, but we don't need to stop scanning. */ while (!error && path->outcome ==XCHK_DIRPATH_SCANNING ) - error =xchk_dirpath_step_up (dl, path); + error =xchk_dirpath_step_up (dl, path, is_metadir);/* Retake the locks we had, mark paths, etc. */ xchk_ilock (sc,XFS_ILOCK_EXCL );
fs/xfs/scrub/findparent.c +13 -0
@@ -172,6 +172,10 @@ xrep_findparent_walk_directory(*/ lock_mode =xfs_ilock_data_map_shared (dp); +/* Don't mix metadata and regular directory trees. */ +if (xfs_is_metadir_inode (dp) !=xfs_is_metadir_inode (sc->ip)) + goto out_unlock; +/* * If this directory is known to be sick, we cannot scan it reliably * and must abort.
@@ -368,6 +372,12 @@ xrep_findparent_confirm(return 0 ; } +/* The metadata root directory always points to itself. */ +if (sc->ip == sc->mp->m_metadirip) { + *parent_ino = sc->mp->m_sb.sb_metadirino; +return 0 ; + } +/* Unlinked dirs can point anywhere; point them up to the root dir. */ if (VFS_I (sc->ip)->i_nlink ==0 ) { *parent_ino =xchk_inode_rootdir_inum (sc->ip);
@@ -415,6 +425,9 @@ xrep_findparent_self_reference(if (sc->ip->i_ino == sc->mp->m_sb.sb_rootino)return sc->mp->m_sb.sb_rootino; +if (sc->ip->i_ino == sc->mp->m_sb.sb_metadirino) +return sc->mp->m_sb.sb_metadirino; +if (VFS_I (sc->ip)->i_nlink ==0 )return xchk_inode_rootdir_inum (sc->ip);
fs/xfs/scrub/parent.c +14 -0
@@ -132,6 +132,14 @@ xchk_parent_validate(return 0 ; } +/* Is this the metadata root dir? Then '..' must point to itself. */ +if (sc->ip == mp->m_metadirip) { +if (sc->ip->i_ino != mp->m_sb.sb_metadirino || + sc->ip->i_ino != parent_ino) +xchk_fblock_set_corrupt (sc,XFS_DATA_FORK ,0 ); +return 0 ; + } +/* '..' must not point to ourselves. */ if (sc->ip->i_ino == parent_ino) {xchk_fblock_set_corrupt (sc,XFS_DATA_FORK ,0 );
@@ -185,6 +193,12 @@ xchk_parent_validate( goto out_unlock; } +/* Metadata and regular inodes cannot cross trees. */ +if (xfs_is_metadir_inode (dp) !=xfs_is_metadir_inode (sc->ip)) { +xchk_fblock_set_corrupt (sc,XFS_DATA_FORK ,0 ); + goto out_unlock; + } +/* Look for a directory entry in the parent pointing to the child. */ error =xchk_dir_walk (sc, dp, xchk_parent_actor, &spc);if (!xchk_fblock_xref_process_error (sc,XFS_DATA_FORK ,0 , &error))
fs/xfs/scrub/trace.h +1 -0
@@ -1753,6 +1753,7 @@ DEFINE_XCHK_DIRPATH_EVENT(xchk_dirpath_badgen);DEFINE_XCHK_DIRPATH_EVENT (xchk_dirpath_nondir_parent);DEFINE_XCHK_DIRPATH_EVENT (xchk_dirpath_unlinked_parent);DEFINE_XCHK_DIRPATH_EVENT (xchk_dirpath_found_next_step); +DEFINE_XCHK_DIRPATH_EVENT (xchk_dirpath_crosses_tree);TRACE_DEFINE_ENUM (XCHK_DIRPATH_SCANNING );TRACE_DEFINE_ENUM (XCHK_DIRPATH_DELETE );
PATCH 25/29 xfs: check the metadata directory inumber in superblocks
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
When metadata directories are enabled, make sure that the secondary superblocks point to the metadata directory. This isn't strictly required because the secondaries are only used to recover damaged filesystems, and the metadir root inumber is fixed.
--- fs/xfs/scrub/agheader.c | 5 +++++ 1 file changed, 5 insertions(+)
fs/xfs/scrub/agheader.c +5 -0
@@ -144,6 +144,11 @@ xchk_superblock(if (sb->sb_rootino !=cpu_to_be64 (mp->m_sb.sb_rootino))xchk_block_set_preen (sc, bp); +if (xfs_has_metadir (sc->mp)) { +if (sb->sb_metadirino !=cpu_to_be64 (mp->m_sb.sb_metadirino)) +xchk_block_set_preen (sc, bp); + } +if (sb->sb_rbmino !=cpu_to_be64 (mp->m_sb.sb_rbmino))xchk_block_set_preen (sc, bp);
PATCH 26/29 xfs: move repair temporary files to the metadata directory tree
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
Due to resource acquisition rules, we have to create the ondisk temporary files used to stage a filesystem repair before we can acquire a reference to the inode that we actually want to repair. Therefore, we do not know at tempfile creation time whether the tempfile will belong to the regular directory tree or the metadata directory tree.
This distinction becomes important when the swapext code tries to figure out the quota accounting of the two files whose mappings are being swapped. The swapext code assumes that accounting updates are required for a file if dqattach attaches dquots. Metadir files are never accounted in quota, which means that swapext must not update the quota accounting when swapping in a repaired directory/xattr/rtbitmap structure.
Prior to the swapext call, therefore, both files must be marked as METADIR for dqattach so that dqattach will ignore them. Add support for a repair tempfile to be switched to the metadir tree and switched back before being released so that ifree will just free the file.
--- fs/xfs/scrub/common.c | 5 ++ fs/xfs/scrub/tempfile.c | 97 +++++++++++++++++++++++++++++++++++++++++++++++ fs/xfs/scrub/tempfile.h | 3 + 3 files changed, 105 insertions(+)
fs/xfs/scrub/common.c +5 -0
@@ -39,6 +39,7 @@#include "scrub/trace.h" #include "scrub/repair.h" #include "scrub/health.h" +#include "scrub/tempfile.h" /* Common code for the metadata scrubbers. */
@@ -1090,6 +1091,10 @@ xchk_setup_inode_contents(if (error)return error; + error =xrep_tempfile_adjust_directory_tree (sc); +if (error) +return error; +/* Lock the inode so the VFS cannot touch this file. */ xchk_ilock (sc,XFS_IOLOCK_EXCL );
fs/xfs/scrub/tempfile.c +97 -0
115 lines not on this page · raw message
fs/xfs/scrub/tempfile.h +3 -0
@@ -10,6 +10,8 @@int xrep_tempfile_create (struct xfs_scrub *sc,uint16_t mode);void xrep_tempfile_rele (struct xfs_scrub *sc); +int xrep_tempfile_adjust_directory_tree (struct xfs_scrub *sc); +bool xrep_tempfile_iolock_nowait (struct xfs_scrub *sc);int xrep_tempfile_iolock_polled (struct xfs_scrub *sc);void xrep_tempfile_iounlock (struct xfs_scrub *sc);
@@ -42,6 +44,7 @@ static inline void xrep_tempfile_iolock_both(struct xfs_scrub *sc) xchk_ilock(sc, XFS_IOLOCK_EXCL); }# define xrep_is_tempfile (ip) (false) +# define xrep_tempfile_adjust_directory_tree (sc) (0)# define xrep_tempfile_rele (sc)#endif /* CONFIG_XFS_ONLINE_REPAIR */
PATCH 27/29 xfs: check metadata directory file path connectivity
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
Create a new scrubber type that checks that well known metadata directory paths are connected to the metadata inode that the incore structures think is in use. For example, check that "/quota/user" in the metadata directory tree actually points to mp->m_quotainfo->qi_uquotaip->i_ino.
--- fs/xfs/Makefile | 1 fs/xfs/libxfs/xfs_fs.h | 13 +++ fs/xfs/libxfs/xfs_health.h | 4 + fs/xfs/scrub/common.h | 1 fs/xfs/scrub/health.c | 1 fs/xfs/scrub/metapath.c | 174 ++++++++++++++++++++++++++++++++++++++++++++ fs/xfs/scrub/scrub.c | 9 ++ fs/xfs/scrub/scrub.h | 2 + fs/xfs/scrub/stats.c | 1 fs/xfs/scrub/trace.c | 1 fs/xfs/scrub/trace.h | 36 +++++++++ fs/xfs/xfs_health.c | 1 12 files changed, 241 insertions(+), 3 deletions(-) create mode 100644 fs/xfs/scrub/metapath.c
fs/xfs/Makefile +1 -0
@@ -174,6 +174,7 @@ xfs-y += $(addprefix scrub/, \ inode.o \ iscan.o \ listxattr.o \ + metapath.o \ nlinks.o \ parent.o \ readdir.o \
fs/xfs/libxfs/xfs_fs.h +12 -1
@@ -199,6 +199,7 @@ struct xfs_fsop_geom {#define XFS_FSOP_GEOM_SICK_QUOTACHECK (1 << 6)/* quota counts */ #define XFS_FSOP_GEOM_SICK_NLINKS (1 << 7)/* inode link counts */ #define XFS_FSOP_GEOM_SICK_METADIR (1 << 8)/* metadata directory */ +#define XFS_FSOP_GEOM_SICK_METAPATH (1 << 9)/* metadir tree path */ /* Output for XFS_FS_COUNTS */ typedef struct xfs_fsop_counts {
@@ -732,9 +733,10 @@ struct xfs_scrub_metadata {#define XFS_SCRUB_TYPE_NLINKS 26/* inode link counts */ #define XFS_SCRUB_TYPE_HEALTHY 27/* everything checked out ok */ #define XFS_SCRUB_TYPE_DIRTREE 28/* directory tree structure */ +#define XFS_SCRUB_TYPE_METAPATH 29/* metadata directory tree paths */ /* Number of scrub subcommands. */ -#define XFS_SCRUB_TYPE_NR 29 +#define XFS_SCRUB_TYPE_NR 30/* * This special type code only applies to the vectored scrub implementation.
@@ -812,6 +814,15 @@ struct xfs_scrub_vec_head {#define XFS_SCRUB_VEC_FLAGS_ALL (0) +/* +* i: sm_ino values for XFS_SCRUB_TYPE_METAPATH to select a metadata file for +* path checking. +*/ +#define XFS_SCRUB_METAPATH_PROBE (0)/* do we have a metapath scrubber? */ + +/* Number of metapath sm_ino values */ +#define XFS_SCRUB_METAPATH_NR (1) +/* * ioctl limits */
fs/xfs/libxfs/xfs_health.h +3 -1
@@ -63,6 +63,7 @@ struct xfs_da_args;#define XFS_SICK_FS_QUOTACHECK (1 << 4)/* quota counts */ #define XFS_SICK_FS_NLINKS (1 << 5)/* inode link counts */ #define XFS_SICK_FS_METADIR (1 << 6)/* metadata directory tree */ +#define XFS_SICK_FS_METAPATH (1 << 7)/* metadata directory tree path */ /* Observable health issues for realtime volume metadata. */ #define XFS_SICK_RT_BITMAP (1 << 0)/* realtime bitmap */
@@ -107,7 +108,8 @@ struct xfs_da_args;XFS_SICK_FS_PQUOTA | \XFS_SICK_FS_QUOTACHECK | \XFS_SICK_FS_NLINKS | \ - XFS_SICK_FS_METADIR) +XFS_SICK_FS_METADIR | \ + XFS_SICK_FS_METAPATH) #define XFS_SICK_RT_PRIMARY (XFS_SICK_RT_BITMAP | \XFS_SICK_RT_SUMMARY )
fs/xfs/scrub/common.h +1 -0
@@ -73,6 +73,7 @@ int xchk_setup_xattr(struct xfs_scrub *sc);int xchk_setup_symlink (struct xfs_scrub *sc);int xchk_setup_parent (struct xfs_scrub *sc);int xchk_setup_dirtree (struct xfs_scrub *sc); +int xchk_setup_metapath (struct xfs_scrub *sc);#ifdef CONFIG_XFS_RT int xchk_setup_rtbitmap (struct xfs_scrub *sc);int xchk_setup_rtsummary (struct xfs_scrub *sc);
fs/xfs/scrub/health.c +1 -0
@@ -109,6 +109,7 @@ static const struct xchk_health_map type_to_health_flag[XFS_SCRUB_TYPE_NR] = { [XFS_SCRUB_TYPE_QUOTACHECK] = { XHG_FS, XFS_SICK_FS_QUOTACHECK }, [XFS_SCRUB_TYPE_NLINKS] = { XHG_FS, XFS_SICK_FS_NLINKS }, [XFS_SCRUB_TYPE_DIRTREE] = { XHG_INO, XFS_SICK_INO_DIRTREE }, + [XFS_SCRUB_TYPE_METAPATH] = { XHG_FS, XFS_SICK_FS_METAPATH }, };/* Return the health status mask for this scrub type. */
fs/xfs/scrub/metapath.c new file +174 -0
174 lines not on this page · raw message
fs/xfs/scrub/scrub.c +9 -0
@@ -442,6 +442,13 @@ static const struct xchk_meta_ops meta_scrub_ops[] = { .has = xfs_has_parent, .repair = xrep_dirtree, }, + [XFS_SCRUB_TYPE_METAPATH] = { /* metadata directory tree path */ + .type = ST_GENERIC, + .setup = xchk_setup_metapath, + .scrub = xchk_metapath, + .has = xfs_has_metadir, + .repair = xrep_notsupported, + }, }; static int
@@ -489,6 +496,8 @@ xchk_validate_inputs(if (sm->sm_agno || (sm->sm_gen && !sm->sm_ino)) goto out;break ; +case ST_GENERIC : +break ;default : goto out; }
fs/xfs/scrub/scrub.h +2 -0
@@ -73,6 +73,7 @@ enum xchk_type {ST_PERAG ,/* per-AG metadata */ ST_FS ,/* per-FS metadata */ ST_INODE ,/* per-inode metadata */ + ST_GENERIC, /* determined by the scrubber */ }; struct xchk_meta_ops {
@@ -255,6 +256,7 @@ int xchk_xattr(struct xfs_scrub *sc);int xchk_symlink (struct xfs_scrub *sc);int xchk_parent (struct xfs_scrub *sc);int xchk_dirtree (struct xfs_scrub *sc); +int xchk_metapath (struct xfs_scrub *sc);#ifdef CONFIG_XFS_RT int xchk_rtbitmap (struct xfs_scrub *sc);int xchk_rtsummary (struct xfs_scrub *sc);
fs/xfs/scrub/stats.c +1 -0
@@ -80,6 +80,7 @@ static const char *name_map[XFS_SCRUB_TYPE_NR] = { [XFS_SCRUB_TYPE_QUOTACHECK] = "quotacheck", [XFS_SCRUB_TYPE_NLINKS] = "nlinks", [XFS_SCRUB_TYPE_DIRTREE] = "dirtree", + [XFS_SCRUB_TYPE_METAPATH] = "metapath", };/* Format the scrub stats into a text buffer, similar to pcp style. */
fs/xfs/scrub/trace.c +1 -0
@@ -20,6 +20,7 @@#include "xfs_dir2.h" #include "xfs_rmap.h" #include "xfs_parent.h" +#include "xfs_metafile.h" #include "scrub/scrub.h" #include "scrub/xfile.h" #include "scrub/xfarray.h"
fs/xfs/scrub/trace.h +35 -1
@@ -70,6 +70,7 @@ TRACE_DEFINE_ENUM(XFS_SCRUB_TYPE_NLINKS);TRACE_DEFINE_ENUM (XFS_SCRUB_TYPE_HEALTHY );TRACE_DEFINE_ENUM (XFS_SCRUB_TYPE_DIRTREE );TRACE_DEFINE_ENUM (XFS_SCRUB_TYPE_BARRIER ); +TRACE_DEFINE_ENUM (XFS_SCRUB_TYPE_METAPATH );#define XFS_SCRUB_TYPE_STRINGS \ { XFS_SCRUB_TYPE_PROBE, "probe" }, \
@@ -101,7 +102,8 @@ TRACE_DEFINE_ENUM(XFS_SCRUB_TYPE_BARRIER); { XFS_SCRUB_TYPE_NLINKS, "nlinks" }, \ { XFS_SCRUB_TYPE_HEALTHY, "healthy" }, \ { XFS_SCRUB_TYPE_DIRTREE, "dirtree" }, \ - { XFS_SCRUB_TYPE_BARRIER, "barrier" } + { XFS_SCRUB_TYPE_BARRIER, "barrier" }, \ + { XFS_SCRUB_TYPE_METAPATH, "metapath" } #define XFS_SCRUB_FLAG_STRINGS \ { XFS_SCRUB_IFLAG_REPAIR, "repair" }, \
@@ -1916,6 +1918,38 @@ TRACE_EVENT(xchk_dirtree_live_update, __get_str(name)) ); +DECLARE_EVENT_CLASS (xchk_metapath_class, + TP_PROTO(struct xfs_scrub *sc, const char *path, + struct xfs_inode *dp, xfs_ino_t ino), +TP_ARGS (sc, path, dp, ino), +TP_STRUCT__entry ( + __field(dev_t, dev) + __field(xfs_ino_t, scrub_ino) + __field(xfs_ino_t, parent_ino) + __field(xfs_ino_t, ino) +__string (name, path) + ), +TP_fast_assign ( + __entry->dev = sc->mp->m_super->s_dev; + __entry->scrub_ino = sc->ip ? sc->ip->i_ino : NULLFSINO; + __entry->parent_ino = dp ? dp->i_ino : NULLFSINO; + __entry->ino = ino; + __assign_str(name); + ), +TP_printk ("dev %d:%d ino 0x%llx parent_ino 0x%llx name '%s' ino 0x%llx" , +MAJOR (__entry->dev),MINOR (__entry->dev), + __entry->scrub_ino, + __entry->parent_ino, +__get_str (name), + __entry->ino) +); +#define DEFINE_XCHK_METAPATH_EVENT (name) \ +DEFINE_EVENT(xchk_metapath_class, name, \ + TP_PROTO(struct xfs_scrub *sc, const char *path, \ + struct xfs_inode *dp, xfs_ino_t ino), \ + TP_ARGS(sc, path, dp, ino)) +DEFINE_XCHK_METAPATH_EVENT (xchk_metapath_lookup); +/* repair tracepoints */ #if IS_ENABLED (CONFIG_XFS_ONLINE_REPAIR )
fs/xfs/xfs_health.c +1 -0
@@ -381,6 +381,7 @@ static const struct ioctl_sick_map fs_map[] = { { XFS_SICK_FS_QUOTACHECK, XFS_FSOP_GEOM_SICK_QUOTACHECK }, { XFS_SICK_FS_NLINKS, XFS_FSOP_GEOM_SICK_NLINKS }, { XFS_SICK_FS_METADIR, XFS_FSOP_GEOM_SICK_METADIR }, + { XFS_SICK_FS_METAPATH, XFS_FSOP_GEOM_SICK_METAPATH }, { 0, 0 }, };
PATCH 28/29 xfs: confirm dotdot target before replacing it during a repair
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
xfs_dir_replace trips an assertion if you tell it to change a dirent to point to an inumber that it already points at. Look up the dotdot entry directly to confirm that we need to make a change.
--- fs/xfs/scrub/dir_repair.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-)
fs/xfs/scrub/dir_repair.c +8 -4
@@ -1638,6 +1638,7 @@ xrep_dir_swap( struct xrep_dir *rd) {struct xfs_scrub *sc = rd->sc; +xfs_ino_t ino;bool ip_local, temp_local;int error =0 ;
@@ -1655,14 +1656,17 @@ xrep_dir_swap(/* * Reset the temporary directory's '..' entry to point to the parent -* that we found. The temporary directory was created with the root -* directory as the parent, so we can skip this if repairing a -* subdirectory of the root. +* that we found. The dirent replace code asserts if the dirent +* already points at the new inumber, so we look it up here. * * It's also possible that this replacement could also expand a sf * tempdir into block format. */ -if (rd->pscan.parent_ino != sc->mp->m_rootip->i_ino) { + error =xchk_dir_lookup (sc, rd->sc->tempip, &xfs_name_dotdot, &ino); +if (error) +return error; + +if (rd->pscan.parent_ino != ino) { error =xrep_dir_replace (rd, rd->sc->tempip, &xfs_name_dotdot, rd->pscan.parent_ino, rd->tx.req.resblks);if (error)