xfsprogs: metadata directories and realtime groups
Hi Andrey,
This patchbomb completes the review of userspace support for the metadata directory tree and realtime allocation group code that was merged into kernel 6.13-rc1. I now submit this for xfsprogs 6.13.
As with last time, I'm presenting the libxfs sync for 6.13 a bit differently than I've done traditionally. Whereas I usually do all the kernel sync and only then go to work on the surrounding utilities, I noticed that the conversion of xfs_perag to be a subclass of generic xfs_group objects and the introduction of xfs_rtgroup objects causes a lot of changes in the utilities.
As a result, I decided that it'd be easier to take care of the libxfs sync for only the metadata directory tree code and the utility changes *before* moving on to the allocation groups restructuring. That's why there are nine patchsets instead of five. I hope that makes it easier to tackle.
Note that this is /not/ the last code I intend to submit for xfsprogs 6.13 -- I found a few more bugs while examining Christoph's zoned storage support code and will submit those when I return from vacation. This patchbomb merely covers everything that is ready for merge.
As always, you can browse / pull the branch from here:
https://git.kernel.org/pub/scm/linux/kernel/git/djwong/xfsprogs-dev.git/log/?h=realtime-quotas_2024-12-23
--D
PATCH 1/8 xfsprogs: bug fixes for 6.12
Hi all,
Bug fixes for 6.12.
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=xfs-6.12-fixes
xfsprogs git tree:
https://git.kernel.org/cgit/linux/kernel/git/djwong/xfsprogs-dev.git/log/?h=xfs-6.12-fixes
---
Commits in this patchset:
* xfs_repair: fix maximum file offset comparison
* man: fix ioctl_xfs_commit_range man page install
* man: document the -n parent mkfs option
--- man/man2/ioctl_xfs_commit_range.2 | 2 +- man/man8/mkfs.xfs.8.in | 12 ++++++++++++ repair/dinode.c | 2 +- repair/globals.c | 1 - repair/globals.h | 1 - repair/prefetch.c | 2 +- repair/versions.c | 7 +------ 7 files changed, 16 insertions(+), 11 deletions(-)
PATCH 1/3 xfs_repair: fix maximum file offset comparison
From: Darrick J. Wong <[email protected]>
When running generic/525 with rtinherit=1 and rextsize=28k, generic/525 trips over the following block mapping:
data offset 2251799813685247 startblock 7 (0/7) count 1 flag 0 data offset 2251799813685248 startblock 8 (0/8) count 6 flag 1
with this error:
inode 155 - extent exceeds max offset - start 2251799813685248, count 6, physical block 8
This is due to an incorrect check in xfs_repair, which tries to validate that a block mapping cannot exceed what it thinks is the maximum file offset. Unfortunately, the check is wrong, because only br_startoff is subject to the 2^52-1 limit -- not br_startoff + br_blockcount.
Nowadays libxfs provides a symbol XFS_MAX_FILEOFF for the maximum allowable file block offset that can be mapped into a file. Use this instead of the open-coded logic in versions.c and correct all the other checks. Note that this problem only surfaced when rtgroups were enabled because hch changed xfs_repair to use the same tree-based block state data structure that we use for AGs when rtgroups are enabled.
--- repair/dinode.c | 2 +- repair/globals.c | 1 - repair/globals.h | 1 - repair/prefetch.c | 2 +- repair/versions.c | 7 +------ 5 files changed, 3 insertions(+), 10 deletions(-)
repair/dinode.c +1 -1
@@ -491,7 +491,7 @@ _("inode %" PRIu64 " - bad extent overflows - start %" PRIu64 ", " }/* Ensure this extent does not extend beyond the max offset */ if (irec.br_startoff + irec.br_blockcount -1 > - fs_max_file_offset) { +XFS_MAX_FILEOFF ) { do_warn( _("inode %" PRIu64 " - extent exceeds max offset - start %" PRIu64 ", " "count %" PRIu64 ", physical block %" PRIu64 "\n"),
repair/globals.c +0 -1
@@ -83,7 +83,6 @@ int inodes_per_block;unsigned int glob_agcount;int chunks_pblock;/* # of 64-ino chunks per allocation */ int max_symlink_blocks; -int64_t fs_max_file_offset;/* realtime info */
repair/globals.h +0 -1
@@ -124,7 +124,6 @@ extern int inodes_per_block;extern unsigned int glob_agcount;extern int chunks_pblock;/* # of 64-ino chunks per allocation */ extern int max_symlink_blocks; -extern int64_t fs_max_file_offset;/* realtime info */
repair/prefetch.c +1 -1
@@ -185,7 +185,7 @@ pf_read_bmbt_reclist(if (((i >0 ) && (op + cp > irec.br_startoff)) || (irec.br_blockcount ==0 ) || - (irec.br_startoff >= fs_max_file_offset)) + (irec.br_startoff + irec.br_blockcount -1 >=XFS_MAX_FILEOFF )) goto out_free; if (!libxfs_verify_fsbno(mp, irec.br_startblock) ||
repair/versions.c +1 -6
@@ -180,10 +180,5 @@ _("WARNING: you have a V1 inode filesystem. It would be converted to a\n" fs_ino_alignment = mp->m_sb.sb_inoalignmt; } -/* -* calculate maximum file offset for this geometry -*/ - fs_max_file_offset =0x7fffffffffffffffLL >> mp->m_sb.sb_blocklog; - -return (0 ); +return 0 ; }
PATCH 2/3 man: fix ioctl_xfs_commit_range man page install
In reply to Darrick J. WongFrom: Jan Palus <[email protected]>
INSTALL_MAN uses first symbol in .SH NAME section for both source and destination filename hence it needs to match current filename. since ioctl_xfs_commit_range.2 documents both ioctl_xfs_start_commit as well as ioctl_xfs_commit_range ensure they are listed in order INSTALL_MAN expects.
--- man/man2/ioctl_xfs_commit_range.2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
man/man2/ioctl_xfs_commit_range.2 +1 -1
@@ -22,8 +22,8 @@ .\" %%%LICENSE_END .TH IOCTL-XFS-COMMIT-RANGE 2 2024-02-18 "XFS" .SH NAME -ioctl_xfs_start_commit \- prepare to exchange the contents of two files ioctl_xfs_commit_range \- conditionally exchange the contents of parts of two files +ioctl_xfs_start_commit \- prepare to exchange the contents of two files .SH SYNOPSIS .br .B #include <sys/ioctl.h>
PATCH 3/3 man: document the -n parent mkfs option
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
Document the -n parent option to mkfs.xfs so that users will actually know how to turn on directory parent pointers.
--- man/man8/mkfs.xfs.8.in | 12 ++++++++++++ 1 file changed, 12 insertions(+)
man/man8/mkfs.xfs.8.in +12 -0
@@ -902,6 +902,18 @@ .SH OPTIONS enabled, and cannot be turned off. .IP In other words, this option is only tunable on the deprecated V4 format. +.TP +.BI parent= value +This feature creates back references from child files to parent directories +so that online repair can reconstruct broken directory files. +The value is either 0 to disable the feature, or 1 to create parent pointers. + +By default, +.B mkfs.xfs +will not create parent pointers. +This feature is only available for filesystems created with the (default) +.B \-m crc=1 +option set. .RE .PP .PD 0
PATCH 2/8 libxfs: metadata inode directory trees
In reply to Darrick J. WongHi all,
Synchronize libxfs with the kernel.
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
xfsprogs git tree:
https://git.kernel.org/cgit/linux/kernel/git/djwong/xfsprogs-dev.git/log/?h=metadata-directory-tree-sync
---
Commits in this patchset:
* xfs: remove the redundant xfs_alloc_log_agf
* xfs: sb_spino_align is not verified
* 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: 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: convert remaining trace points to pass pag structures
* xfs: split xfs_initialize_perag
* xfs: insert the pag structures into the xarray later
* 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: move draining of deferred operations to the generic group structure
* xfs: move the online repair rmap hooks 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: add group based bno conversion helpers
* xfs: store a generic group structure in the intents
* xfs: constify the xfs_sb predicates
* xfs: rename metadata inode predicates
* xfs: define the on-disk format for the metadir feature
* xfs: iget for metadata inodes
* xfs: enforce metadata inode flag
* xfs: read and write metadata inode directory tree
* xfs: disable the agi rotor for metadata inodes
* xfs: advertise metadata directory feature
* xfs: allow bulkstat to return metadata directories
* xfs: adjust xfs_bmap_add_attrfork for metadir
* xfs: record health problems with the metadata directory
* xfs: check metadata directory file path connectivity
--- db/check.c | 2 db/fsmap.c | 10 - db/info.c | 7 - db/inode.c | 4 db/iunlink.c | 6 - include/libxfs.h | 2 include/xfs_inode.h | 11 + include/xfs_mount.h | 45 +++- include/xfs_trace.h | 31 ++- include/xfs_trans.h | 3 libfrog/radix-tree.h | 9 + libxfs/Makefile | 6 + libxfs/defer_item.c | 35 ++- libxfs/init.c | 8 - libxfs/inode.c | 55 +++++ libxfs/iunlink.c | 11 + libxfs/libxfs_api_defs.h | 15 + libxfs/libxfs_priv.h | 10 + libxfs/trans.c | 39 +++ libxfs/util.c | 4 libxfs/xfs_ag.c | 246 ++++++++-------------- libxfs/xfs_ag.h | 189 ++++++++++------- libxfs/xfs_ag_resv.c | 22 +- libxfs/xfs_alloc.c | 104 +++++---- libxfs/xfs_alloc.h | 7 - libxfs/xfs_alloc_btree.c | 30 +-- libxfs/xfs_attr.c | 5 libxfs/xfs_bmap.c | 7 - libxfs/xfs_bmap.h | 2 libxfs/xfs_btree.c | 38 +-- libxfs/xfs_btree.h | 3 libxfs/xfs_btree_mem.c | 6 - libxfs/xfs_format.h | 121 +++++++++-- libxfs/xfs_fs.h | 25 ++ libxfs/xfs_group.c | 223 ++++++++++++++++++++ libxfs/xfs_group.h | 131 ++++++++++++ libxfs/xfs_health.h | 51 ++--- libxfs/xfs_ialloc.c | 175 +++++++++------- libxfs/xfs_ialloc_btree.c | 29 +-- libxfs/xfs_inode_buf.c | 90 ++++++++ libxfs/xfs_inode_buf.h | 3 libxfs/xfs_inode_util.c | 6 - libxfs/xfs_log_format.h | 2 libxfs/xfs_metadir.c | 480 +++++++++++++++++++++++++++++++++++++++++++ libxfs/xfs_metadir.h | 47 ++++ libxfs/xfs_metafile.c | 52 +++++ libxfs/xfs_metafile.h | 31 +++ libxfs/xfs_ondisk.h | 2 libxfs/xfs_refcount.c | 33 +-- libxfs/xfs_refcount.h | 2 libxfs/xfs_refcount_btree.c | 17 +- libxfs/xfs_rmap.c | 42 ++-- libxfs/xfs_rmap.h | 6 - libxfs/xfs_rmap_btree.c | 28 +-- libxfs/xfs_sb.c | 54 ++++- libxfs/xfs_types.c | 9 - libxfs/xfs_types.h | 10 + repair/agbtree.c | 27 +- repair/bmap_repair.c | 11 - repair/bulkload.c | 9 - repair/dino_chunks.c | 2 repair/dinode.c | 12 + repair/phase2.c | 17 +- repair/phase5.c | 6 - repair/rmap.c | 12 + 65 files changed, 2032 insertions(+), 705 deletions(-) create mode 100644 libxfs/xfs_group.c create mode 100644 libxfs/xfs_group.h create mode 100644 libxfs/xfs_metadir.c create mode 100644 libxfs/xfs_metadir.h create mode 100644 libxfs/xfs_metafile.c create mode 100644 libxfs/xfs_metafile.h
PATCH 1/36 xfs: remove the redundant xfs_alloc_log_agf
From: Long Li <[email protected]>
Source kernel commit: 8b9b261594d8ef218ef4d0e732dad153f82aab49
There are two invocations of xfs_alloc_log_agf in xfs_alloc_put_freelist. The AGF does not change between the two calls. Although this does not pose any practical problems, it seems like a small mistake. Therefore, fix it by removing the first xfs_alloc_log_agf invocation.
--- libxfs/xfs_alloc.c | 2 -- 1 file changed, 2 deletions(-)
libxfs/xfs_alloc.c +0 -2
@@ -3152,8 +3152,6 @@ xfs_alloc_put_freelist( logflags |=XFS_AGF_BTREEBLKS ; } -xfs_alloc_log_agf (tp, agbp, logflags); -ASSERT (be32_to_cpu (agf->agf_flcount) <=xfs_agfl_size (mp)); agfl_bno =xfs_buf_to_agfl_bno (agflbp);
PATCH 2/36 xfs: sb_spino_align is not verified
In reply to Darrick J. WongFrom: Dave Chinner <[email protected]>
Source kernel commit: 59e43f5479cce106d71c0b91a297c7ad1913176c
It's just read in from the superblock and used without doing any validity checks at all on the value.
--- libxfs/xfs_sb.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+)
libxfs/xfs_sb.c +14 -0
@@ -395,6 +395,20 @@ xfs_validate_sb_common( sbp->sb_inoalignmt, align);return -EINVAL ; } + +if (!sbp->sb_spino_align || + sbp->sb_spino_align > sbp->sb_inoalignmt || + (sbp->sb_inoalignmt % sbp->sb_spino_align) !=0 ) { +xfs_warn (mp, +"Sparse inode alignment (%u) is invalid." , + sbp->sb_spino_align); +return -EINVAL ; + } + }else if (sbp->sb_spino_align) { +xfs_warn (mp, +"Sparse inode alignment (%u) should be zero." , + sbp->sb_spino_align); +return -EINVAL ; } }else if (sbp->sb_qflags & (XFS_PQUOTA_ENFD |XFS_GQUOTA_ENFD |XFS_PQUOTA_CHKD |XFS_GQUOTA_CHKD )) {
PATCH 3/36 xfs: remove the unused pagb_count field in struct xfs_perag
In reply to Darrick J. WongFrom: Christoph Hellwig <[email protected]>
Source kernel commit: 4e071d79e477189a6c318f598634799e50921994
--- libxfs/xfs_ag.c | 1 - libxfs/xfs_ag.h | 1 - 2 files changed, 2 deletions(-)
libxfs/xfs_ag.c +0 -1
@@ -325,7 +325,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__ */
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 4/36 xfs: remove the unused pag_active_wq field in struct xfs_perag
In reply to Darrick J. WongFrom: Christoph Hellwig <[email protected]>
Source kernel commit: 9943b45732905a70496fc44368ab85b230c70db4
pag_active_wq is only woken, but never waited for.
--- libxfs/xfs_ag.c | 4 +--- libxfs/xfs_ag.h | 1 - 2 files changed, 1 insertion(+), 4 deletions(-)
libxfs/xfs_ag.c +1 -3
@@ -105,8 +105,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); }/*
@@ -324,7 +323,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__ */
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 5/36 xfs: pass a pag to xfs_difree_inode_chunk
In reply to Darrick J. WongFrom: Christoph Hellwig <[email protected]>
Source kernel commit: 67ce5ba575354da1542e0579fb8c7a871cbf57b3
We'll want to use more than just the agno field in a bit.
--- libxfs/xfs_ialloc.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
libxfs/xfs_ialloc.c +3 -2
@@ -1969,10 +1969,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;
@@ -2143,7 +2144,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 6/36 xfs: remove the agno argument to xfs_free_ag_extent
In reply to Darrick J. WongFrom: Christoph Hellwig <[email protected]>
Source kernel commit: db129fa01113f767d5b7a6fd339114a962023464
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.
--- include/xfs_trace.h | 2 +- libxfs/defer_item.c | 4 ++-- libxfs/xfs_alloc.c | 10 ++++------ libxfs/xfs_alloc.h | 5 ++--- 4 files changed, 9 insertions(+), 12 deletions(-)
include/xfs_trace.h +1 -1
@@ -79,7 +79,7 @@#define trace_xfs_btree_free_block (...) ((void) 0)#define trace_xfs_btree_alloc_block (...) ((void) 0) -#define trace_xfs_free_extent (a,b,c,d,e,f,g) ((void) 0) +#define trace_xfs_free_extent (...) ((void) 0)#define trace_xfs_agf (a,b,c,d) ((void) 0)#define trace_xfs_read_agf (a,b) ((void) 0)#define trace_xfs_alloc_read_agf (a,b) ((void) 0)
libxfs/defer_item.c +2 -2
@@ -181,8 +181,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_extent_free_cancel_item (item);return error;
libxfs/xfs_alloc.c +4 -6
@@ -2033,7 +2033,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,
@@ -2354,19 +2353,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)
@@ -4006,8 +4005,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;
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.
PATCH 7/36 xfs: add xfs_agbno_to_fsb and xfs_agbno_to_daddr helpers
In reply to Darrick J. WongFrom: Christoph Hellwig <[email protected]>
Source kernel commit: 856a920ac2bbb2352ef6aa9e1e052f2e80677df7
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.
--- libxfs/xfs_ag.c | 2 +- libxfs/xfs_ag.h | 16 ++++++++++++++++ libxfs/xfs_alloc.c | 14 ++++++-------- libxfs/xfs_btree.c | 7 +++---- libxfs/xfs_ialloc.c | 29 +++++++++++++---------------- libxfs/xfs_ialloc_btree.c | 2 +- libxfs/xfs_refcount.c | 11 ++++------- libxfs/xfs_refcount_btree.c | 3 +-- 8 files changed, 45 insertions(+), 39 deletions(-)
libxfs/xfs_ag.c +1 -1
@@ -867,7 +867,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 ;
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 */
libxfs/xfs_alloc.c +6 -8
@@ -1255,7 +1255,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;
@@ -2929,9 +2929,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; }
@@ -3590,7 +3589,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);
@@ -3642,7 +3641,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;
@@ -3655,8 +3653,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 ;
libxfs/xfs_btree.c +3 -4
@@ -1015,21 +1015,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++; }
@@ -1089,7 +1088,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 :
libxfs/xfs_ialloc.c +13 -16
@@ -763,8 +763,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;
@@ -806,8 +805,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; }
@@ -819,8 +818,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; }
@@ -855,8 +854,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;
@@ -1973,7 +1972,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;
@@ -1984,8 +1982,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 ); }
@@ -2031,9 +2028,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;
@@ -2503,7 +2500,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);
@@ -2533,7 +2530,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);
libxfs/xfs_ialloc_btree.c +1 -1
@@ -119,7 +119,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;
libxfs/xfs_refcount.c +4 -7
@@ -1153,8 +1153,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,
@@ -1216,8 +1215,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,
@@ -1319,7 +1317,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));
@@ -1955,8 +1953,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);
libxfs/xfs_refcount_btree.c +1 -2
@@ -73,8 +73,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 ) {
PATCH 8/36 xfs: add a xfs_agino_to_ino helper
In reply to Darrick J. WongFrom: Christoph Hellwig <[email protected]>
Source kernel commit: 6abd82ab6ea48430c13caebaad436ca6b5f2c34d
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.
--- libxfs/xfs_ag.h | 8 ++++++++ libxfs/xfs_ialloc.c | 24 +++++++++++------------- 2 files changed, 19 insertions(+), 13 deletions(-)
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 */
libxfs/xfs_ialloc.c +11 -13
@@ -909,8 +909,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 ); }
@@ -1329,7 +1328,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);
@@ -1610,7 +1609,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);
@@ -2117,8 +2116,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);/*
@@ -2317,10 +2315,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 ; }
@@ -2451,7 +2449,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 /*
@@ -2466,11 +2464,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 */
PATCH 9/36 xfs: pass a pag to xfs_extent_busy_{search,reuse}
In reply to Darrick J. WongFrom: Christoph Hellwig <[email protected]>
Source kernel commit: b6dc8c6dd2d3f230e1a554f869d6df4568a2dfbb
Replace the [mp,agno] tuple with the perag structure, which will become more useful later.
--- libxfs/libxfs_priv.h | 2 +- libxfs/xfs_alloc.c | 4 ++-- libxfs/xfs_alloc_btree.c | 2 +- libxfs/xfs_rmap_btree.c | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-)
libxfs/libxfs_priv.h +1 -1
@@ -465,7 +465,7 @@ xfs_buf_readahead(#define XFS_EXTENT_BUSY_DISCARDED 0x01/* undergoing a discard op. */ #define XFS_EXTENT_BUSY_SKIP_DISCARD 0x02/* do not discard */ -#define xfs_extent_busy_reuse (mp,ag,bno,len,user) ((void) 0) +#define xfs_extent_busy_reuse (...) ((void) 0)/* avoid unused variable warning */ #define xfs_extent_busy_insert (tp,pag,bno,len,flags)({ \ struct xfs_perag *__foo = pag; \
libxfs/xfs_alloc.c +2 -2
@@ -1248,7 +1248,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 ) {
@@ -3610,7 +3610,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)); }
libxfs/xfs_alloc_btree.c +1 -1
@@ -84,7 +84,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);
libxfs/xfs_rmap_btree.c +1 -1
@@ -101,7 +101,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 );
PATCH 10/36 xfs: pass a perag structure to the xfs_ag_resv_init_error trace point
In reply to Darrick J. WongFrom: Christoph Hellwig <[email protected]>
Source kernel commit: 835ddb592fab75ed96828ee3f12ea44496882d6b
And remove the single instance class indirection for it.
--- libxfs/xfs_ag_resv.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
libxfs/xfs_ag_resv.c +1 -2
@@ -205,8 +205,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);
PATCH 11/36 xfs: pass objects to the xfs_irec_merge_{pre,post} trace points
In reply to Darrick J. WongFrom: Christoph Hellwig <[email protected]>
Source kernel commit: 487092ceaa72448ca3a82ea9fb89768c88f6abec
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.
--- include/xfs_trace.h | 4 ++-- libxfs/xfs_ialloc.c | 7 ++----- 2 files changed, 4 insertions(+), 7 deletions(-)
include/xfs_trace.h +2 -2
@@ -85,8 +85,8 @@#define trace_xfs_alloc_read_agf (a,b) ((void) 0)#define trace_xfs_read_agi (a,b) ((void) 0)#define trace_xfs_ialloc_read_agi (a,b) ((void) 0) -#define trace_xfs_irec_merge_pre (a,b,c,d,e,f) ((void) 0) -#define trace_xfs_irec_merge_post (a,b,c,d) ((void) 0) +#define trace_xfs_irec_merge_pre (...) ((void) 0) +#define trace_xfs_irec_merge_post (...) ((void) 0)#define trace_xfs_iext_insert (a,b,c,d) ((void) 0)#define trace_xfs_iext_remove (a,b,c,d) ((void) 0)
libxfs/xfs_ialloc.c +2 -5
@@ -601,15 +601,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)
PATCH 12/36 xfs: convert remaining trace points to pass pag structures
In reply to Darrick J. WongFrom: Christoph Hellwig <[email protected]>
Source kernel commit: c4ae021bcb6bf8bbb329ce8ef947a43009bc2fe4
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.
--- include/xfs_trace.h | 8 ++++---- libxfs/xfs_alloc.c | 4 ++-- libxfs/xfs_ialloc.c | 4 ++-- libxfs/xfs_inode_util.c | 4 ++-- 4 files changed, 10 insertions(+), 10 deletions(-)
include/xfs_trace.h +4 -4
@@ -81,10 +81,10 @@#define trace_xfs_free_extent (...) ((void) 0)#define trace_xfs_agf (a,b,c,d) ((void) 0) -#define trace_xfs_read_agf (a,b) ((void) 0) -#define trace_xfs_alloc_read_agf (a,b) ((void) 0) -#define trace_xfs_read_agi (a,b) ((void) 0) -#define trace_xfs_ialloc_read_agi (a,b) ((void) 0) +#define trace_xfs_read_agf (...) ((void) 0) +#define trace_xfs_alloc_read_agf (...) ((void) 0) +#define trace_xfs_read_agi (...) ((void) 0) +#define trace_xfs_ialloc_read_agi (...) ((void) 0)#define trace_xfs_irec_merge_pre (...) ((void) 0)#define trace_xfs_irec_merge_post (...) ((void) 0)
libxfs/xfs_alloc.c +2 -2
@@ -3354,7 +3354,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)),
@@ -3385,7 +3385,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)) !=
libxfs/xfs_ialloc.c +2 -2
@@ -2724,7 +2724,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)),
@@ -2755,7 +2755,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,
libxfs/xfs_inode_util.c +2 -2
@@ -439,8 +439,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
PATCH 13/36 xfs: split xfs_initialize_perag
In reply to Darrick J. WongFrom: Christoph Hellwig <[email protected]>
Source kernel commit: 201c5fa342af75adaf762fd6c63380bb8001762d
Factor out a xfs_perag_alloc helper that allocates a single perag structure.
--- libxfs/xfs_ag.c | 121 ++++++++++++++++++++++++++++++++----------------------- libxfs/xfs_ag.h | 4 +- 2 files changed, 72 insertions(+), 53 deletions(-)
libxfs/xfs_ag.c +70 -51
@@ -270,6 +270,10 @@ xfs_agino_range(return __xfs_agino_range (mp,xfs_ag_block_count (mp, agno), first, last); } +/* +* Update the perag of the previous tail AG if it has been changed during +* recovery (i.e. recovery of a growfs). +*/ int xfs_update_last_ag_size( struct xfs_mount *mp,
@@ -287,69 +291,57 @@ xfs_update_last_ag_size(return 0 ; } -int -xfs_initialize_perag ( +static int +xfs_perag_alloc (struct xfs_mount *mp, -xfs_agnumber_t old_agcount, -xfs_agnumber_t new_agcount, -xfs_rfsblock_t dblocks, -xfs_agnumber_t *maxagi) +xfs_agnumber_t index, +xfs_agnumber_t agcount, +xfs_rfsblock_t dblocks) {struct xfs_perag *pag; -xfs_agnumber_t index;int error; -for (index = old_agcount; index < new_agcount; index++) { - pag =kzalloc (sizeof (*pag),GFP_KERNEL ); -if (!pag) { - error = -ENOMEM ; - goto out_unwind_new_pags; - } - pag->pag_agno = index; - pag->pag_mount = mp; + pag =kzalloc (sizeof (*pag),GFP_KERNEL ); +if (!pag) +return -ENOMEM ; - error =xa_insert (&mp->m_perags, index, pag,GFP_KERNEL ); -if (error) { -WARN_ON_ONCE (error == -EBUSY ); - goto out_free_pag; - } + 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); +/* 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; + 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 ); +/* 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); - } +/* +* 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); - index =xfs_set_inode_alloc (mp, new_agcount); - -if (maxagi) - *maxagi = index; - - mp->m_ag_prealloc_blocks =xfs_prealloc_blocks (mp);return 0 ; out_remove_pag:
@@ -357,8 +349,35 @@ xfs_initialize_perag( pag =xa_erase (&mp->m_perags, index); out_free_pag:kfree (pag); +return error; +} + +int +xfs_initialize_perag ( +struct xfs_mount *mp, +xfs_agnumber_t orig_agcount, +xfs_agnumber_t new_agcount, +xfs_rfsblock_t dblocks, +xfs_agnumber_t *maxagi) +{ +xfs_agnumber_t index; +int error; + +if (orig_agcount >= new_agcount) +return 0 ; + +for (index = orig_agcount; index < new_agcount; index++) { + error =xfs_perag_alloc (mp, index, new_agcount, dblocks); +if (error) + goto out_unwind_new_pags; + } + + *maxagi =xfs_set_inode_alloc (mp, new_agcount); + mp->m_ag_prealloc_blocks =xfs_prealloc_blocks (mp); +return 0 ; + out_unwind_new_pags: -xfs_free_perag_range (mp, old_agcount, index); +xfs_free_perag_range (mp, orig_agcount, index);return error; }
libxfs/xfs_ag.h +2 -2
@@ -142,8 +142,8 @@ __XFS_AG_OPSTATE(prefers_metadata, PREFERS_METADATA) __XFS_AG_OPSTATE(allows_inodes, ALLOWS_INODES) __XFS_AG_OPSTATE(agfl_needs_reset, AGFL_NEEDS_RESET) -int xfs_initialize_perag (struct xfs_mount *mp,xfs_agnumber_t old_agcount, -xfs_agnumber_t agcount,xfs_rfsblock_t dcount, +int xfs_initialize_perag (struct xfs_mount *mp,xfs_agnumber_t orig_agcount, +xfs_agnumber_t new_agcount,xfs_rfsblock_t dcount,xfs_agnumber_t *maxagi);void xfs_free_perag_range (struct xfs_mount *mp,xfs_agnumber_t first_agno,xfs_agnumber_t end_agno);
PATCH 14/36 xfs: insert the pag structures into the xarray later
In reply to Darrick J. WongFrom: Christoph Hellwig <[email protected]>
Source kernel commit: d66496578b2a099ea453f56782f1cd2bf63a8029
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.
--- libxfs/xfs_ag.c | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-)
libxfs/xfs_ag.c +15 -16
@@ -305,15 +305,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);
@@ -329,10 +320,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
@@ -342,12 +330,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 15/36 xfs: factor out a generic xfs_group structure
In reply to Darrick J. WongFrom: Christoph Hellwig <[email protected]>
Source kernel commit: e9c4d8bfb26c13c41b73fdf4183d3df2d392101e
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.
--- db/fsmap.c | 6 +- db/info.c | 2 - db/iunlink.c | 2 - include/xfs_mount.h | 6 +- include/xfs_trace.h | 7 ++ libfrog/radix-tree.h | 9 ++ libxfs/Makefile | 2 + libxfs/defer_item.c | 6 +- libxfs/init.c | 8 +- libxfs/iunlink.c | 11 ++- libxfs/xfs_ag.c | 139 +++++++----------------------------- libxfs/xfs_ag.h | 81 +++++++++++++++++---- libxfs/xfs_ag_resv.c | 19 +++-- libxfs/xfs_alloc.c | 39 +++++----- libxfs/xfs_alloc_btree.c | 2 - libxfs/xfs_bmap.c | 2 - libxfs/xfs_btree.c | 6 +- libxfs/xfs_group.c | 168 +++++++++++++++++++++++++++++++++++++++++++ libxfs/xfs_group.h | 41 ++++++++++ libxfs/xfs_ialloc.c | 40 +++++----- libxfs/xfs_ialloc_btree.c | 16 ++-- libxfs/xfs_refcount.c | 4 + libxfs/xfs_refcount_btree.c | 8 +- libxfs/xfs_rmap.c | 4 + libxfs/xfs_rmap_btree.c | 7 +- libxfs/xfs_sb.c | 6 +- libxfs/xfs_types.h | 8 ++ repair/agbtree.c | 27 +++---- repair/bmap_repair.c | 4 - repair/bulkload.c | 9 +- repair/phase2.c | 10 +-- repair/phase5.c | 2 - repair/rmap.c | 10 +-- 33 files changed, 455 insertions(+), 256 deletions(-) create mode 100644 libxfs/xfs_group.c create mode 100644 libxfs/xfs_group.h
db/fsmap.c +3 -3
@@ -64,7 +64,7 @@ fsmap( info.nr =0 ;for_each_perag_range (mp, start_ag, end_ag, pag) { -if (pag->pag_agno == end_ag) +if (pag_agno (pag) == end_ag) high.rm_startblock =XFS_FSB_TO_AGBNO (mp, end_fsb); error = -libxfs_alloc_read_agf (pag,NULL ,0 , &agbp);
@@ -82,7 +82,7 @@ fsmap(return ; } - info.agno = pag->pag_agno; + info.agno =pag_agno (pag); error = -libxfs_rmap_query_range (bt_cur, &low, &high, fsmap_fn, &info);if (error) {
@@ -97,7 +97,7 @@ fsmap(libxfs_btree_del_cursor (bt_cur,XFS_BTREE_NOERROR );libxfs_buf_relse (agbp); -if (pag->pag_agno == start_ag) +if (pag_agno (pag) == start_ag) low.rm_startblock =0 ; } }
db/info.c +1 -1
@@ -66,7 +66,7 @@ print_agresv_info( {struct xfs_buf *bp;struct xfs_agf *agf; -xfs_agnumber_t agno = pag->pag_agno; +xfs_agnumber_t agno =pag_agno (pag);xfs_extlen_t ask =0 ;xfs_extlen_t used =0 ;xfs_extlen_t free =0 ;
db/iunlink.c +1 -1
@@ -117,7 +117,7 @@ dump_unlinked( bool verbose) {struct xfs_buf *agi_bp; -xfs_agnumber_t agno = pag->pag_agno; +xfs_agnumber_t agno =pag_agno (pag);int error; error = -libxfs_ialloc_read_agi (pag,NULL ,0 , &agi_bp);
include/xfs_mount.h +5 -1
@@ -24,6 +24,10 @@ enum { XFS_LOWSP_MAX, }; +struct xfs_groups { +struct xarray xa; +}; +/* * Define a user-level mount structure with all we need * in order to make use of the numerous XFS_* macros.
@@ -91,7 +95,7 @@ typedef struct xfs_mount {xfs_extlen_t m_ag_prealloc_blocks;/* reserved ag blocks */ uint m_alloc_set_aside;/* space we can't use */ uint m_ag_max_usable;/* max space per AG */ -struct xarray m_perags; +struct xfs_groups m_groups[XG_TYPE_MAX ];uint64_t m_features;/* active filesystem features */ uint64_t m_low_space[XFS_LOWSP_MAX ];uint64_t m_rtxblkmask;/* rt extent block mask */
include/xfs_trace.h +7 -0
@@ -366,4 +366,11 @@#define trace_xfs_iunlink_reload_next (...) ((void) 0)#define trace_xfs_iunlink_remove (...) ((void) 0) +#define trace_xfs_group_get (...) ((void) 0) +#define trace_xfs_group_grab_next_tag (...) ((void) 0) +#define trace_xfs_group_grab (...) ((void) 0) +#define trace_xfs_group_hold (...) ((void) 0) +#define trace_xfs_group_put (...) ((void) 0) +#define trace_xfs_group_rele (...) ((void) 0) +#endif /* __TRACE_H__ */
libfrog/radix-tree.h +9 -0
@@ -72,6 +72,8 @@ struct xarray {struct radix_tree_root r; }; +typedef unsigned xa_mark_t ; +static inline void xa_init (struct xarray *xa) {INIT_RADIX_TREE (&xa->r,GFP_KERNEL );
@@ -98,4 +100,11 @@ static inline int xa_insert(struct xarray *xa, unsigned long index, void *entry, return error; } +static inline void *xa_find (struct xarray *xa,unsigned long *indexp, +unsigned long max,xa_mark_t filter) +{ +/* not implemented */ +return NULL ; +} +#endif /* __LIBFROG_RADIX_TREE_H__ */
libxfs/Makefile +2 -0
@@ -49,6 +49,7 @@ HFILES = \ xfs_dir2.h \ xfs_errortag.h \ xfs_exchmaps.h \ + xfs_group.h \ xfs_ialloc.h \ xfs_ialloc_btree.h \ xfs_inode_buf.h \
@@ -105,6 +106,7 @@ CFILES = buf_mem.c \ xfs_dir2_sf.c \ xfs_dquot_buf.c \ xfs_exchmaps.c \ + xfs_group.c \ xfs_ialloc.c \ xfs_iext_tree.c \ xfs_inode_buf.c \
libxfs/defer_item.c +3 -3
@@ -48,7 +48,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); }/* Get an EFI. */
@@ -215,7 +215,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); }/* Get an RUI. */
@@ -336,7 +336,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); }/* Get an CUI. */
libxfs/init.c +5 -3
@@ -360,7 +360,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;
@@ -373,7 +373,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);
@@ -650,6 +650,7 @@ libxfs_mount(struct xfs_buf *bp;struct xfs_sb *sbp;xfs_daddr_t d; +int i;int error; mp->m_features =xfs_sb_version_to_features (sb);
@@ -667,7 +668,8 @@ libxfs_mount( mp->m_finobt_nores = true;xfs_set_inode32 (mp); mp->m_sb = *sb; -xa_init (&mp->m_perags); +for (i =0 ; i <XG_TYPE_MAX ; i++) +xa_init (&mp->m_groups[i].xa); sbp = &mp->m_sb;spin_lock_init (&mp->m_sb_lock);spin_lock_init (&mp->m_agirotor_lock);
libxfs/iunlink.c +6 -5
@@ -65,9 +65,10 @@ xfs_iunlink_log_dinode( 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 (mp,pag_agno (iup->pag), +XFS_INO_TO_AGINO (mp, ip->i_ino), +be32_to_cpu (dip->di_next_unlinked), + iup->next_agino); dip->di_next_unlinked =cpu_to_be32 (iup->next_agino); offset = ip->i_imap.im_boffset +
@@ -137,14 +138,14 @@ 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 ;xfs_ino_t ino;int error;ASSERT (next_agino !=NULLAGINO ); - ino =XFS_AGINO_TO_INO (mp, pag->pag_agno, next_agino); + ino =XFS_AGINO_TO_INO (mp,pag_agno (pag), next_agino); error =libxfs_iget (mp, tp, ino,XFS_IGET_UNTRUSTED , &next_ip);if (error)return error;
libxfs/xfs_ag.c +27 -112
205 lines not on this page · raw message
libxfs/xfs_ag.h +65 -16
139 lines not on this page · raw message
libxfs/xfs_ag_resv.c +10 -9
@@ -69,6 +69,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;
@@ -91,8 +92,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 ); }/*
@@ -136,8 +137,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
@@ -147,7 +148,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 ;
@@ -169,7 +170,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;
@@ -208,7 +209,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; }
@@ -218,7 +219,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);
@@ -236,7 +237,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;
libxfs/xfs_alloc.c +19 -20
@@ -271,7 +271,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);
@@ -795,7 +795,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++) {
@@ -875,13 +875,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 );
@@ -2424,7 +2423,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. */
@@ -2607,7 +2606,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 );
@@ -3182,7 +3181,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;/*
@@ -3351,13 +3350,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 );
@@ -3380,6 +3379,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;
@@ -3406,7 +3406,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);
@@ -3419,16 +3419,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));
@@ -3646,7 +3645,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 ;
@@ -3859,7 +3858,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);
@@ -3898,7 +3897,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);
@@ -3935,7 +3934,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;/*
libxfs/xfs_alloc_btree.c +1 -1
@@ -176,7 +176,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;
libxfs/xfs_bmap.c +1 -1
@@ -3274,7 +3274,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;
libxfs/xfs_btree.c +3 -3
@@ -370,7 +370,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 ; }
@@ -1310,7 +1310,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 ;
@@ -4742,7 +4742,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 ; }
libxfs/xfs_group.c new file +168 -0
168 lines not on this page · raw message
libxfs/xfs_group.h new file +41 -0
41 lines not on this page · raw message
libxfs/xfs_ialloc.c +20 -20
@@ -137,7 +137,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,
@@ -546,7 +546,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;
@@ -640,7 +640,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;
@@ -875,7 +875,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)
@@ -1066,7 +1066,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 ;
@@ -1117,7 +1117,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 */
@@ -1594,7 +1594,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);
@@ -2048,7 +2048,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;
@@ -2182,7 +2182,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;
@@ -2305,9 +2305,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 ; }
@@ -2368,7 +2368,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;
@@ -2379,7 +2379,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; }
@@ -2429,7 +2429,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 */
@@ -2721,13 +2721,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 );
@@ -2775,7 +2775,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
@@ -3114,13 +3114,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;
libxfs/xfs_ialloc_btree.c +8 -8
@@ -247,7 +247,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; }
@@ -259,7 +259,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; }
@@ -477,7 +477,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,
@@ -503,7 +503,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,
@@ -714,7 +714,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. */
@@ -726,7 +726,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,
@@ -790,10 +790,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);
libxfs/xfs_refcount.c +2 -2
@@ -153,7 +153,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);
@@ -1320,7 +1320,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 ; }
libxfs/xfs_refcount_btree.c +4 -4
@@ -80,7 +80,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);
@@ -168,7 +168,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; }
@@ -360,7 +360,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);
@@ -513,7 +513,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);
libxfs/xfs_rmap.c +2 -2
@@ -212,7 +212,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;
@@ -287,7 +287,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,
libxfs/xfs_rmap_btree.c +3 -4
@@ -226,7 +226,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; }
@@ -646,9 +646,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;
@@ -862,7 +861,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. */
libxfs/xfs_sb.c +3 -3
@@ -1131,7 +1131,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,
@@ -1143,7 +1143,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 ;
@@ -1164,7 +1164,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 ;
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 */
repair/agbtree.c +13 -14
@@ -166,8 +166,7 @@ finish_rebuild(if (resv->used == resv->len)continue ; - fsbno =XFS_AGB_TO_FSB (mp, resv->pag->pag_agno, - resv->agbno + resv->used); + fsbno =xfs_agbno_to_fsb (resv->pag, resv->agbno + resv->used); error =bitmap_set (lost_blocks, fsbno, resv->len - resv->used);if (error) do_error(
@@ -203,7 +202,7 @@ get_bno_rec(struct xfs_btree_cur *cur, struct extent_tree_node *prev_value) { - xfs_agnumber_t agno = cur->bc_ag.pag->pag_agno; + xfs_agnumber_t agno = pag_agno(cur->bc_ag.pag);if (xfs_btree_is_bno (cur->bc_ops)) {if (!prev_value)
@@ -254,7 +253,7 @@ init_freespace_cursors(struct bt_rebuild *btr_bno, struct bt_rebuild *btr_cnt) { - xfs_agnumber_t agno = pag->pag_agno; + xfs_agnumber_t agno = pag_agno(pag);unsigned int agfl_goal;int error;
@@ -377,7 +376,7 @@ get_ino_rec(struct xfs_btree_cur *cur, struct ino_tree_node *prev_value) { - xfs_agnumber_t agno = cur->bc_ag.pag->pag_agno; + xfs_agnumber_t agno = pag_agno(cur->bc_ag.pag);if (xfs_btree_is_ino (cur->bc_ops)) {if (!prev_value)
@@ -482,7 +481,7 @@ init_ino_cursors( struct bt_rebuild *btr_fino) {struct ino_tree_node *ino_rec; -xfs_agnumber_t agno = pag->pag_agno; +xfs_agnumber_t agno =pag_agno (pag);unsigned int ino_recs =0 ;unsigned int fino_recs =0 ;bool finobt;
@@ -615,7 +614,7 @@ get_rmapbt_records(if (ret ==0 )do_error (_ ("ran out of records while rebuilding AG %u rmap btree\n" ), - cur->bc_ag.pag->pag_agno); +pag_agno (cur->bc_ag.pag)); block_rec =libxfs_btree_rec_addr (cur, idx, block); cur->bc_ops->init_rec_from_cur (cur, block_rec);
@@ -632,7 +631,7 @@ init_rmapbt_cursor(unsigned int est_agfreeblocks, struct bt_rebuild *btr) { - xfs_agnumber_t agno = pag->pag_agno; + xfs_agnumber_t agno = pag_agno(pag);int error;if (!xfs_has_rmapbt (sc->mp))
@@ -715,7 +714,7 @@ init_refc_cursor(unsigned int est_agfreeblocks, struct bt_rebuild *btr) { - xfs_agnumber_t agno = pag->pag_agno; + xfs_agnumber_t agno = pag_agno(pag);int error;if (!xfs_has_reflink (sc->mp))
@@ -769,7 +768,7 @@ estimate_allocbt_blocks( unsigned int nr_extents) {/* Account for space consumed by both free space btrees */ -return libxfs_allocbt_calc_size (pag->pag_mount, nr_extents) *2 ; +return libxfs_allocbt_calc_size (pag_mount (pag), nr_extents) *2 ; } static xfs_extlen_t
@@ -777,7 +776,7 @@ estimate_inobt_blocks( struct xfs_perag *pag) {struct ino_tree_node *ino_rec; -xfs_agnumber_t agno = pag->pag_agno; +xfs_agnumber_t agno =pag_agno (pag);unsigned int ino_recs =0 ;unsigned int fino_recs =0 ;xfs_extlen_t ret;
@@ -807,9 +806,9 @@ estimate_inobt_blocks( fino_recs++; } - ret =libxfs_iallocbt_calc_size (pag->pag_mount, ino_recs); -if (xfs_has_finobt (pag->pag_mount)) - ret +=libxfs_iallocbt_calc_size (pag->pag_mount, fino_recs); + ret =libxfs_iallocbt_calc_size (pag_mount (pag), ino_recs); +if (xfs_has_finobt (pag_mount (pag))) + ret +=libxfs_iallocbt_calc_size (pag_mount (pag), fino_recs);return ret; }
repair/bmap_repair.c +1 -3
@@ -129,7 +129,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;
@@ -155,8 +154,7 @@ xrep_bmap_walk_rmap( !(rec->rm_flags & XFS_RMAP_ATTR_FORK))return 0 ; - 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;
repair/bulkload.c +3 -6
@@ -74,11 +74,10 @@ bulkload_add_extent( xfs_agblock_t agbno, xfs_extlen_t len) { -struct xfs_mount *mp = bkl->sc->mp;struct xfs_alloc_arg args = { .tp =NULL ,/* no autoreap */ .oinfo = bkl->oinfo, - .fsbno =XFS_AGB_TO_FSB (mp, pag->pag_agno, agbno), + .fsbno =xfs_agbno_to_fsb (pag, agbno), .len = len, .resv =XFS_AG_RESV_NONE , };
@@ -194,7 +193,7 @@ bulkload_free_extent(* Use EFIs to free the reservations. We don't need to use EFIs here * like the kernel, but we'll do it to keep the code matched. */ - fsbno =XFS_AGB_TO_FSB (sc->mp, resv->pag->pag_agno, free_agbno); + fsbno =xfs_agbno_to_fsb (resv->pag, free_agbno); error = -libxfs_free_extent_later (sc->tp, fsbno, free_aglen, &bkl->oinfo,XFS_AG_RESV_NONE ,XFS_FREE_EXTENT_SKIP_DISCARD );
@@ -290,7 +289,6 @@ bulkload_claim_block( union xfs_btree_ptr *ptr) {struct bulkload_resv *resv; -struct xfs_mount *mp = cur->bc_mp;xfs_agblock_t agbno;/*
@@ -316,8 +314,7 @@ bulkload_claim_block(list_move_tail (&resv->list, &bkl->resv_list);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);return 0 ;
repair/phase2.c +5 -5
@@ -304,13 +304,13 @@ check_fs_free_space(if (error)do_error (_ ("Cannot read AGI %u for upgrade check, err=%d.\n" ), - pag->pag_agno, error); +pag_agno (pag), error); error = -libxfs_alloc_read_agf (pag, tp,0 , &agf_bp);if (error)do_error (_ ("Cannot read AGF %u for upgrade check, err=%d.\n" ), - pag->pag_agno, error); +pag_agno (pag), error); agf = agf_bp->b_addr; agblocks =be32_to_cpu (agf->agf_length);
@@ -326,13 +326,13 @@ check_fs_free_space(if (error ==ENOSPC ) {printf (_ ("Not enough free space would remain in AG %u for metadata.\n" ), - pag->pag_agno); +pag_agno (pag));exit (1 ); }if (error)do_error (_ ("Error %d while checking AG %u space reservation.\n" ), - error, pag->pag_agno); + error,pag_agno (pag));/* * Would the post-upgrade filesystem have enough free space in
@@ -345,7 +345,7 @@ check_fs_free_space(if (!check_free_space (mp, avail, agblocks)) {printf (_ ("AG %u will be low on space after upgrade.\n" ), - pag->pag_agno); +pag_agno (pag));exit (1 ); }libxfs_trans_cancel (tp);
repair/phase5.c +1 -1
@@ -441,7 +441,7 @@ phase5_func(struct bt_rebuild btr_fino;struct bt_rebuild btr_rmap;struct bt_rebuild btr_refc; -xfs_agnumber_t agno = pag->pag_agno; +xfs_agnumber_t agno =pag_agno (pag);int extra_blocks =0 ;uint num_freeblocks;xfs_agblock_t num_extents;
repair/rmap.c +5 -5
@@ -1694,7 +1694,7 @@ xfs_extlen_testimate_rmapbt_blocks ( struct xfs_perag *pag) { -struct xfs_mount *mp = pag->pag_mount; +struct xfs_mount *mp =pag_mount (pag);struct xfs_ag_rmap *x;unsigned long long nr_recs =0 ;
@@ -1707,12 +1707,12 @@ estimate_rmapbt_blocks(* means we can use SEEK_DATA/HOLE on the xfile, which is faster than * walking the entire btree to count records. */ - x = &ag_rmaps[pag->pag_agno]; + x = &ag_rmaps[pag_agno (pag)];if (!rmaps_has_observations (x))return 0 ; nr_recs =xmbuf_bytes (x->ar_xmbtp) /sizeof (struct xfs_rmap_rec ); -return libxfs_rmapbt_calc_size (pag->pag_mount, nr_recs); +return libxfs_rmapbt_calc_size (pag_mount (pag), nr_recs); }/* Estimate the size of the ondisk refcountbt from the incore data. */
@@ -1720,13 +1720,13 @@ xfs_extlen_testimate_refcountbt_blocks ( struct xfs_perag *pag) { -struct xfs_mount *mp = pag->pag_mount; +struct xfs_mount *mp =pag_mount (pag);struct xfs_ag_rmap *x;if (!rmap_needs_work (mp) || !xfs_has_reflink (mp))return 0 ; - x = &ag_rmaps[pag->pag_agno]; + x = &ag_rmaps[pag_agno (pag)];if (!x->ar_refcount_items)return 0 ;
PATCH 16/36 xfs: add a xfs_group_next_range helper
In reply to Darrick J. WongFrom: Christoph Hellwig <[email protected]>
Source kernel commit: 819928770bd91960f88f5a4dfa21b35a1bade61b
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.
--- libxfs/xfs_group.c | 26 ++++++++++++++++++++++++++ libxfs/xfs_group.h | 3 +++ 2 files changed, 29 insertions(+)
libxfs/xfs_group.c +26 -0
@@ -86,6 +86,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. */
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 17/36 xfs: switch perag iteration from the for_each macros to a while based iterator
In reply to Darrick J. WongFrom: Christoph Hellwig <[email protected]>
Source kernel commit: 86437e6abbd2ef040f42ef190264819db6118415
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.
--- db/fsmap.c | 4 ++- db/info.c | 5 ++-- db/iunlink.c | 4 ++- libxfs/xfs_ag.h | 62 +++++++++++++++++++++++--------------------------- libxfs/xfs_sb.c | 15 ++++-------- libxfs/xfs_types.c | 5 ++-- repair/bmap_repair.c | 5 ++-- repair/phase2.c | 7 ++---- repair/phase5.c | 4 ++- 9 files changed, 48 insertions(+), 63 deletions(-)
db/fsmap.c +2 -2
@@ -46,7 +46,7 @@ fsmap(struct xfs_rmap_irec high = {0 };struct xfs_btree_cur *bt_cur;struct xfs_buf *agbp; -struct xfs_perag *pag; +struct xfs_perag *pag =NULL ;int error; eofs =XFS_FSB_TO_BB (mp, mp->m_sb.sb_dblocks);
@@ -63,7 +63,7 @@ fsmap( end_ag =XFS_FSB_TO_AGNO (mp, end_fsb); info.nr =0 ; -for_each_perag_range (mp, start_ag, end_ag, pag) { +while ((pag =xfs_perag_next_range (mp, pag, start_ag, end_ag))) {if (pag_agno (pag) == end_ag) high.rm_startblock =XFS_FSB_TO_AGBNO (mp, end_fsb);
db/info.c +2 -3
@@ -104,8 +104,7 @@ agresv_f(int argc, char **argv) { - struct xfs_perag *pag; -xfs_agnumber_t agno; + struct xfs_perag *pag = NULL;int i;if (argc >1 ) {
@@ -134,7 +133,7 @@ agresv_f(return 0 ; } -for_each_perag (mp, agno, pag) +while ((pag =xfs_perag_next (mp, pag)))print_agresv_info (pag);return 0 ;
db/iunlink.c +2 -2
@@ -144,7 +144,7 @@ dump_iunlinked_f(int argc, char **argv) { - struct xfs_perag *pag; + struct xfs_perag *pag = NULL;xfs_agnumber_t agno =NULLAGNUMBER ;unsigned int bucket =-1U ;bool quiet = false;
@@ -189,7 +189,7 @@ dump_iunlinked_f(return 0 ; } -for_each_perag (mp, agno, pag) +while ((pag =xfs_perag_next (mp, pag)))dump_unlinked (pag, bucket, quiet, verbose);return 0 ;
libxfs/xfs_ag.h +28 -34
74 lines not on this page · raw message
libxfs/xfs_sb.c +5 -10
@@ -1120,14 +1120,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,
@@ -1157,7 +1156,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);
@@ -1171,12 +1170,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; }
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; }
repair/bmap_repair.c +2 -3
@@ -218,12 +218,11 @@ STATIC intxrep_bmap_find_mappings ( struct xrep_bmap *rb) { -struct xfs_perag *pag; -xfs_agnumber_t agno; +struct xfs_perag *pag =NULL ;int error;/* Iterate the rmaps for extents. */ -for_each_perag (rb->sc->mp, agno, pag) { +while ((pag =xfs_perag_next (rb->sc->mp, pag))) { error =xrep_bmap_scan_ag (rb, pag);if (error) {libxfs_perag_put (pag);
repair/phase2.c +3 -4
@@ -274,12 +274,11 @@ check_fs_free_space(const struct check_state *old, struct xfs_sb *new_sb) { - struct xfs_perag *pag; -xfs_agnumber_t agno; + struct xfs_perag *pag = NULL;int error;/* Make sure we have enough space for per-AG reservations. */ -for_each_perag (mp, agno, pag) { +while ((pag =xfs_perag_next (mp, pag))) {struct xfs_trans *tp;struct xfs_agf *agf;struct xfs_buf *agi_bp, *agf_bp;
@@ -365,7 +364,7 @@ check_fs_free_space(* uninitialized so that we don't trip over stale cached counters * after the upgrade/ */ -for_each_perag (mp, agno, pag) { +while ((pag =xfs_perag_next (mp, pag))) {libxfs_ag_resv_free (pag);clear_bit (XFS_AGSTATE_AGF_INIT , &pag->pag_opstate);clear_bit (XFS_AGSTATE_AGI_INIT , &pag->pag_opstate);
repair/phase5.c +2 -2
@@ -632,7 +632,7 @@ void phase5(xfs_mount_t *mp) {struct bitmap *lost_blocks =NULL ; -struct xfs_perag *pag; +struct xfs_perag *pag =NULL ;xfs_agnumber_t agno;int error;
@@ -679,7 +679,7 @@ phase5(xfs_mount_t *mp)if (error)do_error (_ ("cannot alloc lost block bitmap\n" )); -for_each_perag (mp, agno, pag) +while ((pag =xfs_perag_next (mp, pag)))phase5_func (mp, pag, lost_blocks);print_final_rpt ();
PATCH 18/36 xfs: move metadata health tracking to the generic group structure
In reply to Darrick J. WongFrom: Christoph Hellwig <[email protected]>
Source kernel commit: 5c8483cec3fe261a5c1ede7430bab042ed156361
Prepare for also tracking the health status of the upcoming realtime groups by moving the health tracking code to the generic xfs_group structure.
--- libxfs/util.c | 4 ++-- libxfs/xfs_ag.c | 1 - libxfs/xfs_ag.h | 9 --------- libxfs/xfs_group.c | 4 ++++ libxfs/xfs_group.h | 12 ++++++++++++ libxfs/xfs_health.h | 45 +++++++++++++++++---------------------------- 6 files changed, 35 insertions(+), 40 deletions(-)
libxfs/util.c +2 -2
@@ -449,8 +449,8 @@ void xfs_ag_geom_health(struct xfs_perag *pag, struct xfs_ag_geometry *ageo) { }void xfs_fs_mark_sick (struct xfs_mount *mp,unsigned int mask) { }void xfs_agno_mark_sick (struct xfs_mount *mp,xfs_agnumber_t agno,unsigned int mask) { } -void xfs_ag_mark_sick (struct xfs_perag *pag,unsigned int mask) { } -void xfs_ag_measure_sickness (struct xfs_perag *pag,unsigned int *sick, +void xfs_group_mark_sick (struct xfs_group *xg,unsigned int mask) { } +void xfs_group_measure_sickness (struct xfs_group *xg,unsigned int *sick,unsigned int *checked) { *sick =0 ;
libxfs/xfs_ag.c +0 -1
@@ -230,7 +230,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);
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 */
libxfs/xfs_group.c +4 -0
@@ -181,6 +181,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 );
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,
libxfs/xfs_health.h +17 -28
73 lines not on this page · raw message
PATCH 19/36 xfs: move draining of deferred operations to the generic group structure
In reply to Darrick J. WongFrom: Christoph Hellwig <[email protected]>
Source kernel commit: 34cf3a6f3952ecabd54b4fe3d431aa44ce98fe45
Prepare supporting the upcoming realtime groups feature by moving the deferred operation draining to the generic xfs_group structure.
--- libxfs/xfs_ag.c | 7 ++----- libxfs/xfs_ag.h | 9 --------- libxfs/xfs_group.c | 4 ++++ libxfs/xfs_group.h | 9 +++++++++ 4 files changed, 15 insertions(+), 14 deletions(-)
libxfs/xfs_ag.c +2 -5
@@ -110,7 +110,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
@@ -232,7 +231,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);
@@ -240,7 +238,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
@@ -258,8 +256,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; }
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__ */
libxfs/xfs_group.c +4 -0
@@ -159,6 +159,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);
@@ -184,6 +186,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 );
@@ -191,6 +194,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; }
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__ */ };
PATCH 20/36 xfs: move the online repair rmap hooks to the generic group structure
In reply to Darrick J. WongFrom: Christoph Hellwig <[email protected]>
Source kernel commit: eb4a84a3c2bd09efe770fa940fb68e349f90c8c6
Prepare for the upcoming realtime groups feature by moving the online repair rmap hooks to based to the generic xfs_group structure.
--- libxfs/xfs_ag.c | 1 - libxfs/xfs_ag.h | 3 --- libxfs/xfs_group.c | 1 + libxfs/xfs_group.h | 5 +++++ libxfs/xfs_rmap.c | 24 +++++++++++++----------- libxfs/xfs_rmap.h | 4 ++-- 6 files changed, 21 insertions(+), 17 deletions(-)
libxfs/xfs_ag.c +0 -1
@@ -233,7 +233,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);
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__ */ };
libxfs/xfs_group.c +1 -0
@@ -185,6 +185,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);
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__ */ };
libxfs/xfs_rmap.c +13 -11
@@ -834,7 +834,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,
@@ -849,27 +849,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. */
@@ -904,7 +904,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);
@@ -1148,7 +1149,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);
@@ -2619,8 +2621,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 ; }
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
PATCH 21/36 xfs: convert busy extent tracking to the generic group structure
In reply to Darrick J. WongFrom: Christoph Hellwig <[email protected]>
Source kernel commit: adbc76aa0fedcb6da2d1ceb1ce786d1f963afee8
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.
--- libxfs/libxfs_priv.h | 6 +++--- libxfs/xfs_ag.c | 3 --- libxfs/xfs_ag.h | 5 ----- libxfs/xfs_alloc.c | 29 +++++++++++++++++------------ libxfs/xfs_alloc_btree.c | 4 ++-- libxfs/xfs_group.c | 15 +++++++++++++-- libxfs/xfs_group.h | 5 +++++ libxfs/xfs_rmap_btree.c | 4 ++-- 8 files changed, 42 insertions(+), 29 deletions(-)
libxfs/libxfs_priv.h +3 -3
@@ -467,11 +467,11 @@ xfs_buf_readahead(#define xfs_extent_busy_reuse (...) ((void) 0)/* avoid unused variable warning */ -#define xfs_extent_busy_insert(tp,pag,bno,len,flags)({ \ - struct xfs_perag *__foo = pag; \ +#define xfs_extent_busy_insert(tp,xg,bno,len,flags)({ \ + struct xfs_group *__foo = xg; \ __foo = __foo; /* no set-but-unused warning */ \ }) -#define xfs_extent_busy_trim (args,bno,len,busy_gen) ({ \ +#define xfs_extent_busy_trim (group,minlen,maxlen,bno,len,busy_gen) ({ \ unsigned __foo = *(busy_gen); \ *(busy_gen) = __foo; \ false; \
libxfs/xfs_ag.c +0 -3
@@ -228,11 +228,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);
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 */
libxfs/xfs_alloc.c +17 -12
@@ -327,7 +327,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,
@@ -1247,7 +1248,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 ) {
@@ -1360,7 +1361,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
@@ -1753,8 +1755,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;
@@ -1869,8 +1872,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;
@@ -1968,8 +1972,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;
@@ -3609,8 +3614,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);
@@ -4008,7 +4013,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:
libxfs/xfs_alloc_btree.c +2 -2
@@ -84,7 +84,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);
@@ -108,7 +108,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 ; }
libxfs/xfs_group.c +13 -2
@@ -160,6 +160,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);
@@ -184,6 +187,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
@@ -195,9 +201,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; }
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.
libxfs/xfs_rmap_btree.c +2 -2
@@ -101,7 +101,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 );
@@ -135,7 +135,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 );
PATCH 22/36 xfs: add a generic group pointer to the btree cursor
In reply to Darrick J. WongFrom: Christoph Hellwig <[email protected]>
Source kernel commit: 77a530e6c49d22bd4a221d2f059db24fc30094db
Replace the pag pointers in the type specific union with a generic xfs_group pointer. This prepares for adding realtime group support.
--- libxfs/xfs_alloc.c | 8 ++++---- libxfs/xfs_alloc_btree.c | 28 ++++++++++++++-------------- libxfs/xfs_btree.c | 35 ++++++++++++----------------------- libxfs/xfs_btree.h | 3 +-- libxfs/xfs_btree_mem.c | 6 ++---- libxfs/xfs_ialloc.c | 12 +++++++----- libxfs/xfs_ialloc_btree.c | 15 ++++++++------- libxfs/xfs_refcount.c | 17 +++++++++-------- libxfs/xfs_refcount_btree.c | 10 +++++----- libxfs/xfs_rmap.c | 8 +++----- libxfs/xfs_rmap_btree.c | 19 ++++++++++--------- repair/agbtree.c | 6 +++--- repair/bmap_repair.c | 4 ++-- 13 files changed, 80 insertions(+), 91 deletions(-)
libxfs/xfs_alloc.c +4 -4
@@ -271,7 +271,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);
@@ -299,7 +299,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);
@@ -536,7 +536,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 ;
@@ -4038,7 +4038,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);
libxfs/xfs_alloc_btree.c +14 -14
@@ -26,7 +26,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 *
@@ -34,29 +34,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 );
@@ -73,7 +73,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;
@@ -84,7 +84,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);
@@ -102,8 +102,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;
@@ -176,7 +176,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;
@@ -490,7 +490,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;
@@ -516,7 +516,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;
libxfs/xfs_btree.c +12 -23
@@ -223,7 +223,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;
@@ -329,7 +329,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 ;
@@ -370,7 +370,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 ; }
@@ -521,20 +521,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); }
@@ -1015,21 +1003,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++; }
@@ -1088,7 +1077,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 :
@@ -1310,7 +1299,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 ;
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; };
libxfs/xfs_btree_mem.c +2 -4
@@ -56,10 +56,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; }
libxfs/xfs_ialloc.c +7 -5
@@ -137,7 +137,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,
@@ -165,7 +165,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);
@@ -270,8 +270,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 ; }
@@ -2875,7 +2877,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);
libxfs/xfs_ialloc_btree.c +8 -7
@@ -36,7 +36,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); }
@@ -44,7 +44,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); }
@@ -111,7 +111,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 ;
@@ -247,7 +247,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; }
@@ -259,7 +259,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; }
@@ -482,7 +483,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;
@@ -508,7 +509,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;
libxfs/xfs_refcount.c +9 -8
@@ -153,7 +153,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);
@@ -179,7 +179,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);
@@ -1153,7 +1153,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,
@@ -1215,7 +1215,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,
@@ -1309,7 +1309,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))) {
@@ -1357,7 +1357,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 );
@@ -1877,7 +1877,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);
@@ -2025,7 +2026,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);
libxfs/xfs_refcount_btree.c +5 -5
@@ -29,7 +29,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
@@ -67,7 +67,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 ;
@@ -80,7 +80,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);
@@ -168,7 +168,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; }
@@ -364,7 +364,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;
libxfs/xfs_rmap.c +3 -5
@@ -268,9 +268,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
@@ -287,7 +285,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,
@@ -2587,7 +2585,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 ;
libxfs/xfs_rmap_btree.c +10 -9
@@ -56,7 +56,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
@@ -65,14 +65,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 ); }
@@ -86,7 +87,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;
@@ -124,7 +125,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;
@@ -226,7 +227,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; }
@@ -537,7 +538,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;
@@ -652,7 +653,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; }
repair/agbtree.c +3 -3
@@ -202,7 +202,7 @@ get_bno_rec(struct xfs_btree_cur *cur, struct extent_tree_node *prev_value) { - xfs_agnumber_t agno = pag_agno(cur->bc_ag.pag); + xfs_agnumber_t agno = cur->bc_group->xg_gno;if (xfs_btree_is_bno (cur->bc_ops)) {if (!prev_value)
@@ -376,7 +376,7 @@ get_ino_rec(struct xfs_btree_cur *cur, struct ino_tree_node *prev_value) { - xfs_agnumber_t agno = pag_agno(cur->bc_ag.pag); + xfs_agnumber_t agno = cur->bc_group->xg_gno;if (xfs_btree_is_ino (cur->bc_ops)) {if (!prev_value)
@@ -614,7 +614,7 @@ get_rmapbt_records(if (ret ==0 )do_error (_ ("ran out of records while rebuilding AG %u rmap btree\n" ), -pag_agno (cur->bc_ag.pag)); + cur->bc_group->xg_gno); block_rec =libxfs_btree_rec_addr (cur, idx, block); cur->bc_ops->init_rec_from_cur (cur, block_rec);
repair/bmap_repair.c +2 -2
@@ -104,7 +104,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 ;
@@ -154,7 +154,7 @@ xrep_bmap_walk_rmap( !(rec->rm_flags & XFS_RMAP_ATTR_FORK))return 0 ; - 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;
PATCH 23/36 xfs: add group based bno conversion helpers
In reply to Darrick J. WongFrom: Christoph Hellwig <[email protected]>
Source kernel commit: 759cc1989a53024066b0f2ea52c206b4ff8f522c
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.
--- include/xfs_mount.h | 26 +++++++++++++++++++++ libxfs/libxfs_api_defs.h | 1 + libxfs/xfs_group.c | 9 +++++++ libxfs/xfs_group.h | 56 ++++++++++++++++++++++++++++++++++++++++++++++ libxfs/xfs_sb.c | 7 ++++++ repair/bmap_repair.c | 2 +- 6 files changed, 100 insertions(+), 1 deletion(-)
include/xfs_mount.h +26 -0
@@ -26,6 +26,32 @@ enum {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; };/*
libxfs/libxfs_api_defs.h +1 -0
@@ -168,6 +168,7 @@#define xfs_free_extent_later libxfs_free_extent_later#define xfs_free_perag_range libxfs_free_perag_range#define xfs_fs_geometry libxfs_fs_geometry +#define xfs_gbno_to_fsb libxfs_gbno_to_fsb#define xfs_get_initial_prid libxfs_get_initial_prid#define xfs_highbit32 libxfs_highbit32#define xfs_highbit64 libxfs_highbit64
libxfs/xfs_group.c +9 -0
@@ -212,3 +212,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); +}
libxfs/xfs_group.h +56 -0
66 lines not on this page · raw message
libxfs/xfs_sb.c +7 -0
@@ -999,6 +999,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;
@@ -1009,6 +1011,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);
repair/bmap_repair.c +1 -1
@@ -154,7 +154,7 @@ xrep_bmap_walk_rmap( !(rec->rm_flags & XFS_RMAP_ATTR_FORK))return 0 ; - fsbno =xfs_agbno_to_fsb (to_perag (cur->bc_group), rec->rm_startblock); + fsbno =libxfs_gbno_to_fsb (cur->bc_group, rec->rm_startblock);if (rec->rm_flags &XFS_RMAP_BMBT_BLOCK ) { rb->old_bmbt_block_count += rec->rm_blockcount;
PATCH 24/36 xfs: store a generic group structure in the intents
In reply to Darrick J. WongFrom: Christoph Hellwig <[email protected]>
Source kernel commit: e5e5cae05b71aa5b5e291c0e74b4e4d98a0b05d4
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.
--- include/xfs_mount.h | 11 ++++++----- libxfs/defer_item.c | 31 ++++++++++++++++++------------- libxfs/xfs_alloc.h | 2 +- libxfs/xfs_bmap.h | 2 +- libxfs/xfs_refcount.c | 9 +++++---- libxfs/xfs_refcount.h | 2 +- libxfs/xfs_rmap.c | 16 +++++++++------- libxfs/xfs_rmap.h | 2 +- 8 files changed, 42 insertions(+), 33 deletions(-)
include/xfs_mount.h +6 -5
@@ -11,6 +11,7 @@ struct xfs_inode;struct xfs_buftarg ;struct xfs_da_geometry ;struct libxfs_init ; +struct xfs_group ;typedef void (*buf_writeback_fn )(struct xfs_buf *bp);
@@ -328,12 +329,12 @@ struct xfs_defer_drain { /* empty */ };#define xfs_defer_drain_init (dr) ((void)0)#define xfs_defer_drain_free (dr) ((void)0) -#define xfs_perag_intent_get (mp, agno) \ - xfs_perag_get((mp), XFS_FSB_TO_AGNO((mp), (agno))) -#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) -static inline void xfs_perag_intent_hold (struct xfs_perag *pag) {} -static inline void xfs_perag_intent_rele (struct xfs_perag *pag) {} +static inline void xfs_group_intent_hold (struct xfs_group *xg) {} +static inline void xfs_group_intent_rele (struct xfs_group *xg) {}static inline void libxfs_buftarg_drain (struct xfs_buftarg *btp) {
libxfs/defer_item.c +18 -13
@@ -28,6 +28,7 @@#include "xfs_ag.h" #include "xfs_exchmaps.h" #include "defer_item.h" +#include "xfs_group.h" /* Dummy defer item ops, since we don't do logging. */
@@ -48,7 +49,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; }/* Get an EFI. */
@@ -85,7 +86,8 @@ xfs_extent_free_defer_add( {struct xfs_mount *mp = tp->t_mountp; - 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);
@@ -101,7 +103,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); }
@@ -127,7 +129,7 @@ xfs_extent_free_finish_item( agbno =XFS_FSB_TO_AGBNO (tp->t_mountp, xefi->xefi_startblock);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,XFS_AG_RESV_NONE ); }
@@ -179,7 +181,7 @@ xfs_agfl_free_finish_item( agbno =XFS_FSB_TO_AGBNO (mp, xefi->xefi_startblock); oinfo.oi_owner = xefi->xefi_owner; - 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 );
@@ -215,7 +217,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; }/* Get an RUI. */
@@ -253,7 +255,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); }
@@ -264,7 +267,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); }
@@ -336,7 +339,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; }/* Get an CUI. */
@@ -374,7 +377,8 @@ 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); }
@@ -385,7 +389,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); }
@@ -508,7 +512,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. */
@@ -542,7 +547,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. */
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; };
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; };
libxfs/xfs_refcount.c +5 -4
@@ -1357,7 +1357,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 );
@@ -1365,13 +1365,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; }
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;
libxfs/xfs_rmap.c +9 -7
@@ -2585,28 +2585,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,
@@ -2619,8 +2621,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 ; }
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 */
PATCH 25/36 xfs: constify the xfs_sb predicates
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
Source kernel commit: 8d939f4bd7b225d8b157b1329881d2719c0ecb29
Change the xfs_sb predicates to take a const struct xfs_sb pointer because they do not change the superblock.
--- libxfs/xfs_format.h | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-)
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 26/36 xfs: rename metadata inode predicates
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
Source kernel commit: 4d272929a5258074328dae206c935634e0fd1a54
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.
--- libxfs/libxfs_api_defs.h | 2 +- libxfs/xfs_types.c | 4 ++-- libxfs/xfs_types.h | 2 +- repair/rmap.c | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-)
libxfs/libxfs_api_defs.h +1 -1
@@ -199,7 +199,7 @@#define xfs_inode_validate_cowextsize libxfs_inode_validate_cowextsize#define xfs_inode_validate_extsize libxfs_inode_validate_extsize -#define xfs_internal_inum libxfs_internal_inum +#define xfs_is_sb_inum libxfs_is_sb_inum#define xfs_iread_extents libxfs_iread_extents#define xfs_irele libxfs_irele
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); }
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,
repair/rmap.c +1 -1
@@ -814,7 +814,7 @@ rmap_shareable(return false;/* Metadata in files are never shareable */ -if (libxfs_internal_inum (mp, rmap->rm_owner)) +if (libxfs_is_sb_inum (mp, rmap->rm_owner))return false;/* Metadata and unwritten file blocks are not shareable. */
PATCH 27/36 xfs: define the on-disk format for the metadir feature
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
Source kernel commit: 4f3d4dd1b04b2ba0bf236fbaa3c3c0c669aa5a47
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.
--- db/check.c | 2 - db/inode.c | 4 +- include/xfs_inode.h | 6 +++ include/xfs_mount.h | 2 + libxfs/xfs_format.h | 97 +++++++++++++++++++++++++++++++++++++++++------ libxfs/xfs_inode_buf.c | 20 +++++++--- libxfs/xfs_inode_util.c | 2 + libxfs/xfs_log_format.h | 2 - libxfs/xfs_ondisk.h | 2 - libxfs/xfs_sb.c | 10 +++++ repair/dino_chunks.c | 2 - repair/dinode.c | 12 +++--- 12 files changed, 132 insertions(+), 29 deletions(-)
db/check.c +1 -1
@@ -2823,7 +2823,7 @@ process_inode(return ; }if (dip->di_version ==1 ) { - nlink =be16_to_cpu (dip->di_onlink); + nlink =be16_to_cpu (dip->di_metatype); prid =0 ; }else { nlink =be32_to_cpu (dip->di_nlink);
db/inode.c +2 -2
@@ -90,9 +90,9 @@ const field_t inode_core_flds[] = { { "mode", FLDT_UINT16O, OI(COFF(mode)), C1, 0, TYP_NONE }, { "version", FLDT_INT8D, OI(COFF(version)), C1, 0, TYP_NONE }, { "format", FLDT_DINODE_FMT, OI(COFF(format)), C1, 0, TYP_NONE }, - { "nlinkv1", FLDT_UINT16D, OI(COFF(onlink)), inode_core_nlinkv1_count, + { "nlinkv1", FLDT_UINT16D, OI(COFF(metatype)), inode_core_nlinkv1_count, FLD_COUNT, TYP_NONE }, - { "onlink", FLDT_UINT16D, OI(COFF(onlink)), inode_core_onlink_count, + { "onlink", FLDT_UINT16D, OI(COFF(metatype)), inode_core_onlink_count, FLD_COUNT, TYP_NONE }, { "uid", FLDT_UINT32D, OI(COFF(uid)), C1, 0, TYP_NONE }, { "gid", FLDT_UINT32D, OI(COFF(gid)), C1, 0, TYP_NONE },
include/xfs_inode.h +6 -0
@@ -230,6 +230,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 */
@@ -396,6 +397,11 @@ static inline bool xfs_is_always_cow_inode(struct xfs_inode *ip)return false; } +static inline bool xfs_is_metadir_inode (const struct xfs_inode *ip) +{ +return ip->i_diflags2 &XFS_DIFLAG2_METADATA ; +} +extern void libxfs_trans_inode_alloc_buf (struct xfs_trans *,struct xfs_buf *);
include/xfs_mount.h +2 -0
@@ -201,6 +201,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 */ #define __XFS_HAS_FEAT (name,NAME ) \ static inline bool xfs_has_ ## name (struct xfs_mount *mp) \
@@ -246,6 +247,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 ) /* Kernel mount features that we don't support */#define __XFS_UNSUPP_FEAT (name) \
libxfs/xfs_format.h +84 -13
142 lines not on this page · raw message
libxfs/xfs_inode_buf.c +15 -5
@@ -206,12 +206,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));
@@ -312,7 +315,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));
@@ -520,8 +526,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; }
@@ -543,7 +552,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; } }
libxfs/xfs_inode_util.c +2 -0
@@ -221,6 +221,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,
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 */
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);
libxfs/xfs_sb.c +10 -0
@@ -177,6 +177,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; }
@@ -700,6 +702,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
@@ -847,6 +854,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); }/*
repair/dino_chunks.c +1 -1
@@ -896,7 +896,7 @@ process_inode_chunk(set_inode_disk_nlinks (ino_rec, irec_offset, dino->di_version >1 ?be32_to_cpu (dino->di_nlink) - :be16_to_cpu (dino->di_onlink)); + :be16_to_cpu (dino->di_metatype)); }else {set_inode_free (ino_rec, irec_offset);
repair/dinode.c +7 -5
@@ -2231,20 +2231,22 @@ process_check_inode_nlink_version(int dirty =0 ;/* -* if it's a version 2 inode, it should have a zero +* if it's a version 2 non-metadir inode, it should have a zero * onlink field, so clear it. */ -if (dino->di_version >1 && dino->di_onlink !=0 ) { +if (dino->di_version >1 && + !(dino->di_flags2 &cpu_to_be64 (XFS_DIFLAG2_METADATA )) && + dino->di_metatype !=0 ) {if (!no_modify) {do_warn (_ ("clearing obsolete nlink field in version 2 inode %" PRIu64", was %d, now 0\n" ), - lino,be16_to_cpu (dino->di_onlink)); - dino->di_onlink =0 ; + lino,be16_to_cpu (dino->di_metatype)); + dino->di_metatype =0 ; dirty =1 ; }else {do_warn (_ ("would clear obsolete nlink field in version 2 inode %" PRIu64", currently %d\n" ), - lino,be16_to_cpu (dino->di_onlink)); + lino,be16_to_cpu (dino->di_metatype)); } }return dirty;
PATCH 28/36 xfs: iget for metadata inodes
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
Source kernel commit df2e495bb92c84a401b6b90c835a9d1be84a3a0f
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.
--- include/libxfs.h | 1 + include/xfs_inode.h | 5 ++++ libxfs/Makefile | 1 + libxfs/inode.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++ libxfs/libxfs_api_defs.h | 5 ++++ libxfs/xfs_metafile.h | 16 +++++++++++++ 6 files changed, 83 insertions(+) create mode 100644 libxfs/xfs_metafile.h
include/libxfs.h +1 -0
@@ -95,6 +95,7 @@ struct iomap;#include "xfs_btree_mem.h" #include "xfs_parent.h" #include "xfs_ag_resv.h" +#include "xfs_metafile.h" #ifndef ARRAY_SIZE #define ARRAY_SIZE (x) (sizeof(x) / sizeof((x)[0]))
include/xfs_inode.h +5 -0
@@ -210,6 +210,11 @@ static inline struct timespec64 inode_set_ctime_current(struct inode *inode)return now; } +static inline bool inode_wrong_type (const struct inode *inode,umode_t mode) +{ +return (inode->i_mode ^ mode) &S_IFMT ; +} + typedef struct xfs_inode { struct cache_node i_node; struct xfs_mount *i_mount; /* fs mount struct ptr */
libxfs/Makefile +1 -0
@@ -55,6 +55,7 @@ HFILES = \ xfs_inode_buf.h \ xfs_inode_fork.h \ xfs_inode_util.h \ + xfs_metafile.h \ xfs_parent.h \ xfs_quota_defs.h \ xfs_refcount.h \
libxfs/inode.c +55 -0
61 lines not on this page · raw message
libxfs/libxfs_api_defs.h +5 -0
@@ -184,6 +184,7 @@#define xfs_iext_next libxfs_iext_next#define xfs_ifork_zap_attr libxfs_ifork_zap_attr#define xfs_imap_to_bp libxfs_imap_to_bp +#define xfs_initialize_perag libxfs_initialize_perag#define xfs_initialize_perag_data libxfs_initialize_perag_data#define xfs_init_local_fork libxfs_init_local_fork
@@ -208,8 +209,12 @@#define xfs_log_calc_minimum_size libxfs_log_calc_minimum_size#define xfs_log_get_max_trans_res libxfs_log_get_max_trans_res#define xfs_log_sb libxfs_log_sb + +#define xfs_metafile_iget libxfs_metafile_iget +#define xfs_trans_metafile_iget libxfs_trans_metafile_iget#define xfs_mode_to_ftype libxfs_mode_to_ftype#define xfs_mkdir_space_res libxfs_mkdir_space_res +#define xfs_parent_addname libxfs_parent_addname#define xfs_parent_finish libxfs_parent_finish#define xfs_parent_hashval libxfs_parent_hashval
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__ */
PATCH 29/36 xfs: enforce metadata inode flag
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
Source kernel commit: 7297fd0bebbd70efd12f72632a0f3ac49a8f59fe
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.
--- libxfs/xfs_inode_buf.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++++ libxfs/xfs_inode_buf.h | 3 ++ libxfs/xfs_metafile.h | 11 ++++++++ 3 files changed, 84 insertions(+)
libxfs/xfs_inode_buf.c +70 -0
@@ -17,6 +17,7 @@#include "xfs_ialloc.h" #include "xfs_dir2.h" #include "xfs_health.h" +#include "xfs_metafile.h" /*
@@ -486,6 +487,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,
@@ -670,6 +734,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 ; }
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,
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,
PATCH 30/36 xfs: read and write metadata inode directory tree
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
Source kernel commit e0f091c40bf1287a122dcddd8aa4e6ad06ce441f
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.
--- include/libxfs.h | 1 include/xfs_trace.h | 10 + include/xfs_trans.h | 3 libxfs/Makefile | 3 libxfs/libxfs_api_defs.h | 7 + libxfs/libxfs_priv.h | 2 libxfs/trans.c | 39 ++++ libxfs/xfs_metadir.c | 473 ++++++++++++++++++++++++++++++++++++++++++++++ libxfs/xfs_metadir.h | 47 +++++ libxfs/xfs_metafile.c | 52 +++++ libxfs/xfs_metafile.h | 4 11 files changed, 641 insertions(+) create mode 100644 libxfs/xfs_metadir.c create mode 100644 libxfs/xfs_metadir.h create mode 100644 libxfs/xfs_metafile.c
include/libxfs.h +1 -0
@@ -96,6 +96,7 @@ struct iomap;#include "xfs_parent.h" #include "xfs_ag_resv.h" #include "xfs_metafile.h" +#include "xfs_metadir.h" #ifndef ARRAY_SIZE #define ARRAY_SIZE (x) (sizeof(x) / sizeof((x)[0]))
include/xfs_trace.h +10 -0
@@ -360,6 +360,16 @@#define trace_xlog_intent_recovery_failed (...) ((void) 0) +#define trace_xfs_metadir_cancel (...) ((void) 0) +#define trace_xfs_metadir_commit (...) ((void) 0) +#define trace_xfs_metadir_create (...) ((void) 0) +#define trace_xfs_metadir_link (...) ((void) 0) +#define trace_xfs_metadir_lookup (...) ((void) 0) +#define trace_xfs_metadir_start_create (...) ((void) 0) +#define trace_xfs_metadir_start_link (...) ((void) 0) +#define trace_xfs_metadir_teardown (...) ((void) 0) +#define trace_xfs_metadir_try_create (...) ((void) 0) +#define trace_xfs_iunlink_update_bucket (...) ((void) 0)#define trace_xfs_iunlink_update_dinode (...) ((void) 0)#define trace_xfs_iunlink (...) ((void) 0)
include/xfs_trans.h +3 -0
@@ -93,6 +93,9 @@ int libxfs_trans_alloc(struct xfs_mount *mp, struct xfs_trans_res *resp,int libxfs_trans_alloc_inode (struct xfs_inode *ip,struct xfs_trans_res *resv,unsigned int dblocks,unsigned int rblocks,bool force,struct xfs_trans **tpp); +int libxfs_trans_alloc_dir (struct xfs_inode *dp,struct xfs_trans_res *resv, +struct xfs_inode *ip,unsigned int *dblocks, +struct xfs_trans **tpp,int *nospace_error);int libxfs_trans_alloc_rollable (struct xfs_mount *mp,uint blocks,struct xfs_trans **tpp);int libxfs_trans_alloc_empty (struct xfs_mount *mp,struct xfs_trans **tpp);
libxfs/Makefile +3 -0
@@ -55,6 +55,7 @@ HFILES = \ xfs_inode_buf.h \ xfs_inode_fork.h \ xfs_inode_util.h \ + xfs_metadir.h \ xfs_metafile.h \ xfs_parent.h \ xfs_quota_defs.h \
@@ -114,6 +115,8 @@ CFILES = buf_mem.c \ xfs_inode_fork.c \ xfs_inode_util.c \ xfs_ialloc_btree.c \ + xfs_metadir.c \ + xfs_metafile.c \ xfs_log_rlimit.c \ xfs_parent.c \ xfs_refcount.c \
libxfs/libxfs_api_defs.h +7 -0
@@ -176,6 +176,7 @@#define xfs_iallocbt_calc_size libxfs_iallocbt_calc_size#define xfs_iallocbt_maxlevels_ondisk libxfs_iallocbt_maxlevels_ondisk#define xfs_ialloc_read_agi libxfs_ialloc_read_agi +#define xfs_icreate libxfs_icreate#define xfs_idata_realloc libxfs_idata_realloc#define xfs_idestroy_fork libxfs_idestroy_fork#define xfs_iext_first libxfs_iext_first
@@ -212,6 +213,11 @@#define xfs_metafile_iget libxfs_metafile_iget#define xfs_trans_metafile_iget libxfs_trans_metafile_iget +#define xfs_metadir_link libxfs_metadir_link +#define xfs_metadir_lookup libxfs_metadir_lookup +#define xfs_metadir_start_create libxfs_metadir_start_create +#define xfs_metadir_start_link libxfs_metadir_start_link +#define xfs_mode_to_ftype libxfs_mode_to_ftype#define xfs_mkdir_space_res libxfs_mkdir_space_res
@@ -285,6 +291,7 @@#define xfs_trans_add_item libxfs_trans_add_item#define xfs_trans_alloc_empty libxfs_trans_alloc_empty#define xfs_trans_alloc libxfs_trans_alloc +#define xfs_trans_alloc_dir libxfs_trans_alloc_dir#define xfs_trans_alloc_inode libxfs_trans_alloc_inode#define xfs_trans_bdetach libxfs_trans_bdetach#define xfs_trans_bhold libxfs_trans_bhold
libxfs/libxfs_priv.h +2 -0
@@ -181,6 +181,7 @@ enum ce { CE_DEBUG, CE_CONT, CE_NOTE, CE_WARN, CE_ALERT, CE_PANIC };#define XFS_ILOCK_SHARED 0#define XFS_ILOCK_RTBITMAP 0#define XFS_ILOCK_RTSUM 0 +#define XFS_IOLOCK_EXCL 0#define XFS_STATS_INC (mp, count) do { (mp) = (mp); } while (0)#define XFS_STATS_DEC (mp, count, x) do { (mp) = (mp); } while (0)#define XFS_STATS_ADD (mp, count, x) do { (mp) = (mp); } while (0)
@@ -632,6 +633,7 @@ int xfs_bmap_last_extent(struct xfs_trans *tp, struct xfs_inode *ip,/* xfs_inode.h */ #define xfs_iflags_set (ip, flags) do { } while (0) +#define xfs_finish_inode_setup (ip) ((void) 0)/* linux/wordpart.h */
libxfs/trans.c +39 -0
@@ -1185,6 +1185,45 @@ libxfs_trans_alloc_inode(return 0 ; } +/* +* Allocate an transaction, lock and join the directory and child inodes to it, +* and reserve quota for a directory update. @resblks must point to the number +* of blocks to reserve; if not enough space is available, -ENOSPC will be +* returned. @nospace_error is always set to zero here. Userspace does not +* support reservationless creation at all, unlike the kernel. +* +* The ILOCKs will be dropped when the transaction is committed or cancelled. +* +* Caller is responsible for unlocking the inodes manually upon return +*/ +int +libxfs_trans_alloc_dir ( +struct xfs_inode *dp, +struct xfs_trans_res *resv, +struct xfs_inode *ip, +unsigned int *resblks, +struct xfs_trans **tpp, +int *nospace_error) +{ +struct xfs_trans *tp; +struct xfs_mount *mp = ip->i_mount; +int error; + + *nospace_error =0 ; + + error =xfs_trans_alloc (mp, resv, *resblks,0 ,0 , &tp); +if (error) +return error; + +xfs_lock_two_inodes (dp,XFS_ILOCK_EXCL , ip,XFS_ILOCK_EXCL ); + +xfs_trans_ijoin (tp, dp,0 ); +xfs_trans_ijoin (tp, ip,0 ); + + *tpp = tp; +return 0 ; +} +/* * Try to reserve more blocks for a transaction. The single use case we * support is for offline repair -- use a transaction to gather data without
libxfs/xfs_metadir.c new file +473 -0
473 lines not on this page · raw message
libxfs/xfs_metadir.h new file +47 -0
47 lines not on this page · raw message
libxfs/xfs_metafile.c new file +52 -0
52 lines not on this page · raw message
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,
PATCH 31/36 xfs: disable the agi rotor for metadata inodes
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
Source kernel commit: 8651b410ae781cc607159c51dbb0b317b23543b1
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.
--- libxfs/xfs_ialloc.c | 58 +++++++++++++++++++++++++++++++++++---------------- 1 file changed, 40 insertions(+), 18 deletions(-)
libxfs/xfs_ialloc.c +40 -18
@@ -1836,6 +1836,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. *
@@ -1851,31 +1885,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 32/36 xfs: advertise metadata directory feature
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
Source kernel commit: 688828d8f8cdf8b1b917de938a1ce86a93fdbba9
Advertise the existence of the metadata directory feature; this will be used by scrub to decide if it needs to scan the metadir too.
--- libxfs/xfs_fs.h | 1 + libxfs/xfs_sb.c | 2 ++ 2 files changed, 3 insertions(+)
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.
libxfs/xfs_sb.c +2 -0
@@ -1306,6 +1306,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 33/36 xfs: allow bulkstat to return metadata directories
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
Source kernel commit: df866c538ff098baa210b407b822818a415a6e7e
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.)
--- libxfs/xfs_fs.h | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-)
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)
PATCH 34/36 xfs: adjust xfs_bmap_add_attrfork for metadir
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
Source kernel commit: 61b6bdb30a4bee1f3417081aedfe9e346538f897
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.
--- libxfs/xfs_attr.c | 5 ++++- libxfs/xfs_bmap.c | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-)
libxfs/xfs_attr.c +4 -1
@@ -1003,7 +1003,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);
libxfs/xfs_bmap.c +4 -1
@@ -1036,7 +1036,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 35/36 xfs: record health problems with the metadata directory
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
Source kernel commit: be42fc1393d66024eb6415c92f45fab5d1878c3e
Make a report to the health monitoring subsystem any time we encounter something in the metadata directory tree that looks like corruption.
--- libxfs/xfs_fs.h | 1 + libxfs/xfs_health.h | 4 +++- libxfs/xfs_metadir.c | 13 ++++++++++--- 3 files changed, 14 insertions(+), 4 deletions(-)
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 {
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 )
libxfs/xfs_metadir.c +10 -3
@@ -27,6 +27,7 @@#include "xfs_dir2.h" #include "xfs_dir2_priv.h" #include "xfs_parent.h" +#include "xfs_health.h" /* * Metadata Directory Tree
@@ -93,8 +94,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 ;
@@ -102,10 +105,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;
PATCH 36/36 xfs: check metadata directory file path connectivity
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
Source kernel commit: b3c03efa5972f084e40104307dbe432359279cf2
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.
--- libxfs/xfs_fs.h | 13 ++++++++++++- libxfs/xfs_health.h | 4 +++- 2 files changed, 15 insertions(+), 2 deletions(-)
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 */
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 )
PATCH 3/8 xfsprogs: 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.
We start by creating xfs_imeta_* functions to mediate access to metadata inode pointers. This enables the imeta code to abstract inode pointers, whether they're the classic five in the superblock, or the much more complex directory tree. All current users of metadata inodes (rt+quota) are converted to use the boilerplate code.
Next, we define the metadir on-disk format, which consists of marking inodes with a new iflag that says they're metadata. This we use to prevent bulkstat and friends from ever getting their hands on fs metadata.
Finally, we implement metadir operations so that clients can create, delete, zap, and look up metadata inodes by path. Beware that much of this code is only lightly used, because the five current users of metadata inodes don't tend to change them very often. This is likely to change if and when the subvolume and multiple-rt-volume features get written/merged/etc.
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:
* libxfs: constify the xfs_inode predicates
* libxfs: load metadata directory root at mount time
* libxfs: enforce metadata inode flag
* man2: document metadata directory flag in fsgeom ioctl
* man: update scrub ioctl documentation for metadir
* libfrog: report metadata directories in the geometry report
* libfrog: allow METADIR in xfrog_bulkstat_single5
* xfs_io: support scrubbing metadata directory paths
* xfs_db: disable xfs_check when metadir is enabled
* xfs_db: report metadir support for version command
* xfs_db: don't obfuscate metadata directories and attributes
* xfs_db: support metadata directories in the path command
* xfs_db: show the metadata root directory when dumping superblocks
* xfs_db: display di_metatype
* xfs_db: drop the metadata checking code from blockget
* xfs_io: support flag for limited bulkstat of the metadata directory
* xfs_io: support scrubbing metadata directory paths
* xfs_spaceman: report health of metadir inodes too
* xfs_scrub: tread zero-length read verify as an IO error
* xfs_scrub: scan metadata directories during phase 3
* xfs_scrub: re-run metafile scrubbers during phase 5
* xfs_repair: handle sb_metadirino correctly when zeroing supers
* xfs_repair: dont check metadata directory dirent inumbers
* xfs_repair: refactor fixing dotdot
* xfs_repair: refactor marking of metadata inodes
* xfs_repair: refactor root directory initialization
* xfs_repair: refactor grabbing realtime metadata inodes
* xfs_repair: check metadata inode flag
* xfs_repair: use libxfs_metafile_iget for quota/rt inodes
* xfs_repair: rebuild the metadata directory
* xfs_repair: don't let metadata and regular files mix
* xfs_repair: update incore metadata state whenever we create new files
* xfs_repair: pass private data pointer to scan_lbtree
* xfs_repair: mark space used by metadata files
* xfs_repair: adjust keep_fsinos to handle metadata directories
* xfs_repair: metadata dirs are never plausible root dirs
* xfs_repair: drop all the metadata directory files during pass 4
* xfs_repair: truncate and unmark orphaned metadata inodes
* xfs_repair: do not count metadata directory files when doing quotacheck
* xfs_repair: refactor generate_rtinfo
* mkfs.xfs: enable metadata directories
--- db/check.c | 290 ------------------- db/field.c | 2 db/field.h | 1 db/inode.c | 86 +++++- db/inode.h | 2 db/metadump.c | 385 ++++++++++++------------- db/namei.c | 71 ++++- db/sb.c | 16 + include/xfs_inode.h | 12 - include/xfs_mount.h | 1 io/bulkstat.c | 16 + io/scrub.c | 62 ++++ libfrog/bulkstat.c | 3 libfrog/fsgeom.c | 6 libfrog/scrub.c | 14 + libfrog/scrub.h | 2 libxfs/init.c | 26 ++ libxfs/inode.c | 9 + libxfs/libxfs_api_defs.h | 4 man/man2/ioctl_xfs_fsgeometry.2 | 3 man/man2/ioctl_xfs_scrub_metadata.2 | 44 +++ man/man8/mkfs.xfs.8.in | 11 + man/man8/xfs_db.8 | 35 +- man/man8/xfs_io.8 | 13 + mkfs/lts_4.19.conf | 1 mkfs/lts_5.10.conf | 1 mkfs/lts_5.15.conf | 1 mkfs/lts_5.4.conf | 1 mkfs/lts_6.1.conf | 1 mkfs/lts_6.12.conf | 1 mkfs/lts_6.6.conf | 1 mkfs/proto.c | 68 ++++ mkfs/xfs_mkfs.c | 33 ++ repair/agheader.c | 11 + repair/dino_chunks.c | 43 +++ repair/dinode.c | 196 +++++++++++-- repair/dinode.h | 6 repair/dir2.c | 51 +++ repair/globals.c | 8 - repair/globals.h | 8 - repair/incore.h | 63 +++- repair/incore_ino.c | 1 repair/phase1.c | 2 repair/phase2.c | 58 +++- repair/phase4.c | 18 + repair/phase5.c | 12 + repair/phase6.c | 541 +++++++++++++++++++++++------------ repair/pptr.c | 94 ++++++ repair/pptr.h | 2 repair/quotacheck.c | 22 + repair/rt.c | 189 ++++++++---- repair/rt.h | 12 - repair/sb.c | 3 repair/scan.c | 43 ++- repair/scan.h | 7 repair/xfs_repair.c | 56 ++++ scrub/inodes.c | 11 + scrub/inodes.h | 5 scrub/phase3.c | 7 scrub/phase5.c | 102 ++++++- scrub/phase6.c | 24 +- scrub/read_verify.c | 8 + scrub/scrub.c | 18 + scrub/scrub.h | 7 spaceman/health.c | 2 65 files changed, 1949 insertions(+), 903 deletions(-)
PATCH 1/41 libxfs: constify the xfs_inode predicates
From: 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.
--- include/xfs_inode.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)
include/xfs_inode.h +6 -6
@@ -248,7 +248,7 @@ typedef struct xfs_inode {struct inode i_vnode; } xfs_inode_t; -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 ; }
@@ -372,17 +372,17 @@ static inline void drop_nlink(struct inode *inode) inode->i_nlink--; } -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 ; } -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 ; }
@@ -392,12 +392,12 @@ 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 ; } -static inline bool xfs_is_always_cow_inode (struct xfs_inode *ip) +static inline bool xfs_is_always_cow_inode (const struct xfs_inode *ip) {return false; }
PATCH 2/41 libxfs: 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.
--- include/xfs_mount.h | 1 + libxfs/init.c | 26 ++++++++++++++++++++++++++ 2 files changed, 27 insertions(+)
include/xfs_mount.h +1 -0
@@ -91,6 +91,7 @@ typedef struct xfs_mount {uint8_t *m_rsum_cache;struct xfs_inode *m_rbmip;/* pointer to bitmap inode */ struct xfs_inode *m_rsumip;/* pointer to summary inode */ +struct xfs_inode *m_metadirip;/* ptr to metadata directory */ struct xfs_buftarg *m_ddev_targp;struct xfs_buftarg *m_logdev_targp;struct xfs_buftarg *m_rtdev_targp;
libxfs/init.c +26 -0
@@ -619,6 +619,27 @@ libxfs_compute_all_maxlevels( } +/* Mount the metadata files under the metadata directory tree. */ +STATIC void +libxfs_mount_setup_metadir ( +struct xfs_mount *mp) +{ +int error; + +/* Ignore filesystems that are under construction. */ +if (mp->m_sb.sb_inprogress) +return ; + + error = -libxfs_metafile_iget (mp, mp->m_sb.sb_metadirino, +XFS_METAFILE_DIR , &mp->m_metadirip); +if (error) { +fprintf (stderr, +_ ("%s: Failed to load metadir root directory, error %d\n" ), + progname, error); +return ; + } +} +/* * precalculate the low space thresholds for dynamic speculative preallocation. */
@@ -800,6 +821,9 @@ libxfs_mount( }xfs_set_perag_data_loaded (mp); +if (xfs_has_metadir (mp)) +libxfs_mount_setup_metadir (mp); +return mp; out_da:xfs_da_unmount (mp);
@@ -918,6 +942,8 @@ libxfs_umount(int error;libxfs_rtmount_destroy (mp); +if (mp->m_metadirip) +libxfs_irele (mp->m_metadirip);/* * Purge the buffer cache to write all dirty buffers to disk and free
PATCH 3/41 libxfs: 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.
--- libxfs/inode.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-)
libxfs/inode.c +8 -1
@@ -208,7 +208,8 @@ libxfs_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 libxfs_trans_metafile_iget(
@@ -232,6 +233,12 @@ libxfs_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 ;
PATCH 4/41 man2: document metadata directory flag in fsgeom ioctl
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
Document the additions to the fsgeometry ioctl for metadata directory trees.
--- man/man2/ioctl_xfs_fsgeometry.2 | 3 +++ 1 file changed, 3 insertions(+)
man/man2/ioctl_xfs_fsgeometry.2 +3 -0
@@ -214,6 +214,9 @@ .SH FILESYSTEM FEATURE FLAGS .TP .B XFS_FSOP_GEOM_FLAGS_EXCHANGE_RANGE Filesystem can exchange file contents atomically via XFS_IOC_EXCHANGE_RANGE. +.TP +.B XFS_FSOP_GEOM_FLAGS_METADIR +Filesystem contains a metadata directory tree. .RE .SH XFS METADATA HEALTH REPORTING .PP
PATCH 5/41 man: update scrub ioctl documentation for metadir
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
Update the scrub ioctl manpage to reflect the new metadir path scrubber.
--- man/man2/ioctl_xfs_scrub_metadata.2 | 44 +++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+)
man/man2/ioctl_xfs_scrub_metadata.2 +44 -0
@@ -200,6 +200,50 @@ .SH DESCRIPTION Mark everything healthy after a clean scrub run. This clears out all the indirect health problem markers that might remain in the system. + +.TP +.B XFS_SCRUB_TYPE_METAPATH +Check that a metadata directory path actually points to the active metadata +inode. +Metadata inodes are usually cached for the duration of the mount, so this +scrubber ensures that the same inode will still be reachable after an unmount +and mount cycle. +Discrepancies can happen if the directory or parent pointer scrubbers rebuild +a metadata directory but lose a link in the process. +The +.B sm_ino +field should be passed one of the following special values to communicate which +path to check: + +.RS 7 +.TP +.B XFS_SCRUB_METAPATH_RTDIR +Realtime metadata file subdirectory. +.TP +.B XFS_SCRUB_METAPATH_RTBITMAP +Realtime bitmap file. +.TP +.B XFS_SCRUB_METAPATH_RTSUMMARY +Realtime summary file. +.TP +.B XFS_SCRUB_METAPATH_QUOTADIR +Quota metadata file subdirectory. +.TP +.B XFS_SCRUB_METAPATH_USRQUOTA +User quota file. +.TP +.B XFS_SCRUB_METAPATH_GRPQUOTA +Group quota file. +.TP +.B XFS_SCRUB_METAPATH_PRJQUOTA +Project quota file. +.RE + +The values of +.I sm_agno +and +.I sm_gen +must be zero. .RE .PD 1
PATCH 6/41 libfrog: report metadata directories in the geometry report
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
Report the presence of a metadata directory tree in the geometry report.
--- libfrog/fsgeom.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
libfrog/fsgeom.c +4 -2
@@ -33,6 +33,7 @@ xfs_report_geom(int nrext64;int exchangerange;int parent; +int metadir; isint = geo->logstart >0 ; lazycount = geo->flags &XFS_FSOP_GEOM_FLAGS_LAZYSB ?1 :0 ;
@@ -53,13 +54,14 @@ xfs_report_geom( nrext64 = geo->flags &XFS_FSOP_GEOM_FLAGS_NREXT64 ?1 :0 ; exchangerange = geo->flags &XFS_FSOP_GEOM_FLAGS_EXCHANGE_RANGE ?1 :0 ; parent = geo->flags &XFS_FSOP_GEOM_FLAGS_PARENT ?1 :0 ; + metadir = geo->flags &XFS_FSOP_GEOM_FLAGS_METADIR ?1 :0 ; printf(_( "meta-data=%-22s isize=%-6d agcount=%u, agsize=%u blks\n" " =%-22s sectsz=%-5u attr=%u, projid32bit=%u\n" " =%-22s crc=%-8u finobt=%u, sparse=%u, rmapbt=%u\n" " =%-22s reflink=%-4u bigtime=%u inobtcount=%u nrext64=%u\n" -" =%-22s exchange=%-3u\n" +" =%-22s exchange=%-3u metadir=%u\n" "data =%-22s bsize=%-6u blocks=%llu, imaxpct=%u\n" " =%-22s sunit=%-6u swidth=%u blks\n" "naming =version %-14u bsize=%-6u ascii-ci=%d, ftype=%d, parent=%d\n"
@@ -70,7 +72,7 @@ xfs_report_geom("" , geo->sectsize, attrversion, projid32bit,"" , crcs_enabled, finobt_enabled, spinodes, rmapbt_enabled,"" , reflink_enabled, bigtime_enabled, inobtcount, nrext64, -"" , exchangerange, +"" , exchangerange, metadir,"" , geo->blocksize, (unsigned long long )geo->datablocks, geo->imaxpct, "", geo->sunit, geo->swidth,
PATCH 7/41 libfrog: allow METADIR in xfrog_bulkstat_single5
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
This is a valid flag for a single-file bulkstat, so add that to the filter.
--- libfrog/bulkstat.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
libfrog/bulkstat.c +2 -1
@@ -53,7 +53,8 @@ xfrog_bulkstat_single5(struct xfs_bulkstat_req *req;int ret; -if (flags & ~(XFS_BULK_IREQ_SPECIAL |XFS_BULK_IREQ_NREXT64 )) +if (flags & ~(XFS_BULK_IREQ_SPECIAL |XFS_BULK_IREQ_NREXT64 | +XFS_BULK_IREQ_METADIR ))return -EINVAL ;if (xfd->fsgeom.flags &XFS_FSOP_GEOM_FLAGS_NREXT64 )
PATCH 8/41 xfs_io: support scrubbing metadata directory paths
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
Support invoking the metadata directory path scrubber from xfs_io for testing.
--- libfrog/scrub.c | 14 +++++++++++++- libfrog/scrub.h | 2 ++ scrub/scrub.c | 18 ++++++++++++++++++ 3 files changed, 33 insertions(+), 1 deletion(-)
libfrog/scrub.c +13 -1
@@ -154,8 +154,20 @@ const struct xfrog_scrub_descr xfrog_scrubbers[XFS_SCRUB_TYPE_NR] = { .descr = "directory tree structure", .group = XFROG_SCRUB_GROUP_INODE, }, + [XFS_SCRUB_TYPE_METAPATH] = { + .name = "metapath", + .descr = "metadata directory paths", + .group = XFROG_SCRUB_GROUP_METAPATH, + }, +}; + +const struct xfrog_scrub_descr xfrog_metapaths[XFS_SCRUB_METAPATH_NR ] = { + [XFS_SCRUB_METAPATH_PROBE ] = { + .name ="probe" , + .descr ="metapath" , + .group =XFROG_SCRUB_GROUP_NONE , + }, }; -#undef DEP/* Invoke the scrub ioctl. Returns zero or negative error code. */ int
libfrog/scrub.h +2 -0
@@ -15,6 +15,7 @@ enum xfrog_scrub_group {XFROG_SCRUB_GROUP_INODE ,/* per-inode metadata */ XFROG_SCRUB_GROUP_ISCAN ,/* metadata requiring full inode scan */ XFROG_SCRUB_GROUP_SUMMARY ,/* summary metadata */ + XFROG_SCRUB_GROUP_METAPATH, /* metadata directory path */ };/* Catalog of scrub types and names, indexed by XFS_SCRUB_TYPE_* */
@@ -25,6 +26,7 @@ struct xfrog_scrub_descr { };extern const struct xfrog_scrub_descr xfrog_scrubbers[XFS_SCRUB_TYPE_NR ]; +extern const struct xfrog_scrub_descr xfrog_metapaths[XFS_SCRUB_METAPATH_NR ];int xfrog_scrub_metadata (struct xfs_fd *xfd,struct xfs_scrub_metadata *meta);
scrub/scrub.c +18 -0
@@ -53,6 +53,22 @@ static const unsigned int scrub_deps[XFS_SCRUB_TYPE_NR] = { };#undef DEP +static int +format_metapath_descr ( +char *buf, +size_t buflen, +struct xfs_scrub_vec_head *vhead) +{ +const struct xfrog_scrub_descr *sc; + +if (vhead->svh_ino >=XFS_SCRUB_METAPATH_NR ) +return snprintf (buf, buflen,_ ("unknown metadir path %llu" ), + (unsigned long long )vhead->svh_ino); + + sc = &xfrog_metapaths[vhead->svh_ino]; +return snprintf (buf, buflen,"%s" ,_ (sc->descr)); +} +/* Describe the current state of a vectored scrub. */ int format_scrubv_descr(
@@ -89,6 +105,8 @@ format_scrubv_descr(case XFROG_SCRUB_GROUP_ISCAN :case XFROG_SCRUB_GROUP_NONE :return snprintf (buf, buflen,_ ("%s" ),_ (sc->descr)); +case XFROG_SCRUB_GROUP_METAPATH : +return format_metapath_descr (buf, buflen, vhead); }return -1 ; }
PATCH 9/41 xfs_db: disable xfs_check when metadir is enabled
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
As of July 2024, xfs_repair can detect more types of corruptions than xfs_check does. I don't think it makes sense to maintain the xfs_check code anymore, so let's just turn it off for any filesystem that has metadata directory trees.
--- db/check.c | 6 ++++++ 1 file changed, 6 insertions(+)
db/check.c +6 -0
@@ -831,6 +831,12 @@ blockget_f( dbprefix = oldprefix;return 0 ; } + +if (xfs_has_metadir (mp)) { + dbprefix = oldprefix; +return 0 ; + } +check_rootdir ();/* * Check that there are no blocks either
PATCH 10/41 xfs_db: report metadir support for version command
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
Report metadir support if we have it enabled.
--- db/inode.c | 3 +++ db/sb.c | 2 ++ 2 files changed, 5 insertions(+)
db/inode.c +3 -0
@@ -207,6 +207,9 @@ const field_t inode_v3_flds[] = { {"nrext64" ,FLDT_UINT1 ,OI (COFF (flags2) +bitsz (uint64_t) -XFS_DIFLAG2_NREXT64_BIT -1 ),C1 , 0, TYP_NONE }, + { "metadata", FLDT_UINT1, +OI (COFF (flags2) +bitsz (uint64_t) -XFS_DIFLAG2_METADATA_BIT -1 ),C1 , + 0, TYP_NONE }, { NULL } };
db/sb.c +2 -0
@@ -710,6 +710,8 @@ version_string(strcat (s,",EXCHANGE" );if (xfs_has_parent (mp))strcat (s,",PARENT" ); +if (xfs_has_metadir (mp)) +strcat (s,",METADIR" );return s; }
PATCH 11/41 xfs_db: don't obfuscate metadata directories and attributes
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
Don't obfuscate the directory and attribute names of metadata inodes.
--- db/metadump.c | 385 +++++++++++++++++++++++++++------------------------------ 1 file changed, 183 insertions(+), 202 deletions(-)
db/metadump.c +183 -202
@@ -1056,10 +1056,26 @@ generate_obfuscated_name(free (orig_name); } +static inline bool +is_metadata_ino ( +struct xfs_dinode *dip) +{ +if (!xfs_has_metadir (mp) || dip->di_version <3 ) +return false; +return dip->di_flags2 &cpu_to_be64 (XFS_DIFLAG2_METADATA ); +} + +static inline bool +want_obfuscate_dirents (bool is_meta) +{ +return metadump.obfuscate && !is_meta; +} +static void process_sf_dir (struct xfs_dinode *dip) { +bool is_meta =is_metadata_ino (dip);struct xfs_dir2_sf_hdr *sfp;xfs_dir2_sf_entry_t *sfep;uint64_t ino_dir_size;
@@ -1105,7 +1121,7 @@ process_sf_dir( (char *)sfp); } -if (metadump.obfuscate) +if (want_obfuscate_dirents (is_meta))generate_obfuscated_name (libxfs_dir2_sf_get_ino (mp, sfp, sfep), namelen, &sfep->name[0 ]);
@@ -1201,7 +1217,8 @@ maybe_obfuscate_pptr(uint8_t *name, int namelen, const void *value, - int valuelen) + int valuelen, + bool is_meta) { unsigned char old_name[MAXNAMELEN];struct remap_ent *remap;
@@ -1210,7 +1227,7 @@ maybe_obfuscate_pptr(xfs_ino_t parent_ino;int error; -if (!metadump.obfuscate) +if (!metadump.obfuscate || is_meta)return ;if (!(attr_flags &XFS_ATTR_PARENT ))
@@ -1274,9 +1291,10 @@ want_obfuscate_attr(const void *name, unsigned int namelen, const void *value, - unsigned int valuelen) + unsigned int valuelen, + bool is_meta) { - if (!metadump.obfuscate) + if (!metadump.obfuscate || is_meta) return false;/*
@@ -1289,15 +1307,15 @@ want_obfuscate_attr(return true; } +/* +* Obfuscate the attr names and fill the actual values with 'v' (to see a valid +* string length, as opposed to NULLs). +*/ static void process_sf_attr (struct xfs_dinode *dip) { -/* -* with extended attributes, obfuscate the names and fill the actual -* values with 'v' (to see a valid string length, as opposed to NULLs) -*/ - +bool is_meta =is_metadata_ino (dip);struct xfs_attr_sf_hdr *hdr =XFS_DFORK_APTR (dip);struct xfs_attr_sf_entry *asfep =libxfs_attr_sf_firstentry (hdr);int ino_attr_size;
@@ -1338,9 +1356,9 @@ process_sf_attr(if (asfep->flags &XFS_ATTR_PARENT ) {maybe_obfuscate_pptr (asfep->flags, name, namelen, - value, asfep->valuelen); + value, asfep->valuelen, is_meta); }else if (want_obfuscate_attr (asfep->flags, name, namelen, - value, asfep->valuelen)) { + value, asfep->valuelen, is_meta)) {generate_obfuscated_name (0 , asfep->namelen, name);memset (value,'v' , asfep->valuelen); }
@@ -1442,7 +1460,8 @@ static voidprocess_dir_data_block ( char *block, xfs_fileoff_t offset, - int is_block_format) + int is_block_format, + bool is_meta) {/* * we have to rely on the fileoffset and signature of the block to
@@ -1549,7 +1568,7 @@ process_dir_data_block( dir_offset)return ; -if (metadump.obfuscate) +if (want_obfuscate_dirents (is_meta))generate_obfuscated_name (be64_to_cpu (dep->inumber), dep->namelen, &dep->name[0 ]); dir_offset += length;
@@ -1574,7 +1593,8 @@ process_symlink_block(xfs_fsblock_t s, xfs_filblks_t c, typnm_t btype, - xfs_fileoff_t last) + xfs_fileoff_t last, + bool is_meta) { struct bbmap map;char *link;
@@ -1599,7 +1619,7 @@ process_symlink_block(if (xfs_has_crc ((mp))) link +=sizeof (struct xfs_dsymlink_hdr ); -if (metadump.obfuscate) +if (want_obfuscate_dirents (is_meta))obfuscate_path_components (link,XFS_SYMLINK_BUF_SPACE (mp, mp->m_sb.sb_blocksize));if (metadump.zero_stale_data) {
@@ -1650,7 +1670,8 @@ add_remote_vals(static void process_attr_block (char *block, -xfs_fileoff_t offset) +xfs_fileoff_t offset, +bool is_meta) {struct xfs_attr_leafblock *leaf;struct xfs_attr3_icleaf_hdr hdr;
@@ -1730,10 +1751,10 @@ process_attr_block(if (entry->flags &XFS_ATTR_PARENT ) {maybe_obfuscate_pptr (entry->flags, name, local->namelen, value, - valuelen); + valuelen, is_meta); }else if (want_obfuscate_attr (entry->flags, name, local->namelen, value, - valuelen)) { + valuelen, is_meta)) {generate_obfuscated_name (0 , local->namelen, name);memset (value,'v' , valuelen);
@@ -1759,7 +1780,7 @@ process_attr_block(/* do not obfuscate obviously busted pptr */ add_remote_vals (be32_to_cpu (remote->valueblk),be32_to_cpu (remote->valuelen)); - }else if (metadump.obfuscate) { + }else if (want_obfuscate_dirents (is_meta)) {generate_obfuscated_name (0 , remote->namelen, &remote->name[0 ]); add_remote_vals(be32_to_cpu(remote->valueblk),
@@ -1792,7 +1813,8 @@ process_single_fsb_objects(xfs_fsblock_t s, xfs_filblks_t c, typnm_t btype, - xfs_fileoff_t last) + xfs_fileoff_t last, + bool is_meta) { int rval = 1;char *dp;
@@ -1862,12 +1884,13 @@ process_single_fsb_objects(process_dir_leaf_block (dp); }else {process_dir_data_block (dp, o, - last == mp->m_dir_geo->fsbcount); + last == mp->m_dir_geo->fsbcount, + is_meta); } iocur_top->need_crc =1 ;break ;case TYP_ATTR : -process_attr_block (dp, o); +process_attr_block (dp, o, is_meta); iocur_top->need_crc =1 ;break ;default :
@@ -1900,7 +1923,8 @@ process_multi_fsb_dir(xfs_fsblock_t s, xfs_filblks_t c, typnm_t btype, - xfs_fileoff_t last) + xfs_fileoff_t last, + bool is_meta) { char *dp;int rval =1 ;
@@ -1944,7 +1968,8 @@ process_multi_fsb_dir(process_dir_leaf_block (dp); }else {process_dir_data_block (dp, o, - last == mp->m_dir_geo->fsbcount); + last == mp->m_dir_geo->fsbcount, + is_meta); } iocur_top->need_crc =1 ; write:
@@ -1963,6 +1988,38 @@ process_multi_fsb_dir(return rval; } +static typnm_t +ifork_data_type ( +struct xfs_dinode *dip, +int whichfork) +{ +xfs_ino_t ino =be64_to_cpu (dip->di_ino); + +if (whichfork ==XFS_ATTR_FORK ) +return TYP_ATTR ; + +switch (be16_to_cpu (dip->di_mode) &S_IFMT ) { +case S_IFDIR : +return TYP_DIR2 ; +case S_IFLNK : +return TYP_SYMLINK ; +case S_IFREG : +if (ino == mp->m_sb.sb_rbmino) +return TYP_RTBITMAP ; +if (ino == mp->m_sb.sb_rsumino) +return TYP_RTSUMMARY ; +if (ino == mp->m_sb.sb_uquotino) +return TYP_DQBLK ; +if (ino == mp->m_sb.sb_gquotino) +return TYP_DQBLK ; +if (ino == mp->m_sb.sb_pquotino) +return TYP_DQBLK ; +return TYP_DATA ; +default : +return TYP_NONE ; + } +} + static bool is_multi_fsb_object( struct xfs_mount *mp,
@@ -1981,13 +2038,14 @@ process_multi_fsb_objects(xfs_fsblock_t s, xfs_filblks_t c, typnm_t btype, - xfs_fileoff_t last) + xfs_fileoff_t last, + bool is_meta) { switch (btype) { case TYP_DIR2: - return process_multi_fsb_dir(o, s, c, btype, last); + return process_multi_fsb_dir(o, s, c, btype, last, is_meta);case TYP_SYMLINK : -return process_symlink_block (o, s, c, btype, last); +return process_symlink_block (o, s, c, btype, last, is_meta);default :print_warning ("bad type for multi-fsb object %d" , btype);return 1 ;
@@ -1997,10 +2055,13 @@ process_multi_fsb_objects(/* inode copy routines */ static int process_bmbt_reclist ( -xfs_bmbt_rec_t *rp, -int numrecs, -typnm_t btype) +struct xfs_dinode *dip, +int whichfork, +struct xfs_bmbt_rec *rp, +int numrecs) { +bool is_meta =is_metadata_ino (dip); +typnm_t btype =ifork_data_type (dip, whichfork);int i;xfs_fileoff_t o, op =NULLFILEOFF ;xfs_fsblock_t s;
@@ -2009,7 +2070,6 @@ process_bmbt_reclist(xfs_fileoff_t last;xfs_agnumber_t agno;xfs_agblock_t agbno; -bool is_multi_fsb =is_multi_fsb_object (mp, btype);int rval =1 ;if (btype ==TYP_DATA )
@@ -2077,12 +2137,12 @@ process_bmbt_reclist( }/* multi-extent blocks require special handling */ -if (is_multi_fsb) +if (is_multi_fsb_object (mp, btype)) rval =process_multi_fsb_objects (o, s, c, btype, - last); + last, is_meta);else rval =process_single_fsb_objects (o, s, c, btype, - last); + last, is_meta);if (!rval)break ; }
@@ -2090,6 +2150,11 @@ process_bmbt_reclist(return rval; } +struct scan_bmap { +struct xfs_dinode *dip; +int whichfork; +}; + static int scanfunc_bmap( struct xfs_btree_block *block,
@@ -2097,8 +2162,9 @@ scanfunc_bmap(xfs_agblock_t agbno, int level, typnm_t btype, - void *arg) /* ptr to itype */ + void *arg) { + struct scan_bmap *sbm = arg;int i;xfs_bmbt_ptr_t *pp;int nrecs;
@@ -2113,8 +2179,8 @@ scanfunc_bmap( typtab[btype].name, agno, agbno);return 1 ; } -return process_bmbt_reclist (xfs_bmbt_rec_addr (mp, block,1 ), - nrecs, *(typnm_t *)arg); +return process_bmbt_reclist (sbm->dip, sbm->whichfork, +xfs_bmbt_rec_addr (mp, block,1 ), nrecs); }if (nrecs > mp->m_bmap_dmxr[1 ]) {
@@ -2149,23 +2215,17 @@ scanfunc_bmap(static int process_btinode (struct xfs_dinode *dip, -typnm_t itype) +int whichfork) { -xfs_bmdr_block_t *dib; -int i; -xfs_bmbt_ptr_t *pp; -int level; -int nrecs; +struct xfs_bmdr_block *dib = + (struct xfs_bmdr_block *)XFS_DFORK_PTR (dip, whichfork); +int level =be16_to_cpu (dib->bb_level); +int nrecs =be16_to_cpu (dib->bb_numrecs);int maxrecs; -int whichfork; -typnm_t btype; - - whichfork = (itype ==TYP_ATTR ) ?XFS_ATTR_FORK :XFS_DATA_FORK ; - btype = (itype ==TYP_ATTR ) ?TYP_BMAPBTA :TYP_BMAPBTD ; - - dib = (xfs_bmdr_block_t *)XFS_DFORK_PTR (dip, whichfork); - level =be16_to_cpu (dib->bb_level); - nrecs =be16_to_cpu (dib->bb_numrecs); +typnm_t btype = (whichfork ==XFS_ATTR_FORK ) ? +TYP_BMAPBTA :TYP_BMAPBTD ; +xfs_bmbt_ptr_t *pp; +int i;if (level >XFS_BM_MAXLEVELS (mp, whichfork)) {if (metadump.show_warnings)
@@ -2176,8 +2236,8 @@ process_btinode( }if (level ==0 ) { -return process_bmbt_reclist (xfs_bmdr_rec_addr (dib,1 ), - nrecs, itype); +return process_bmbt_reclist (dip, whichfork, +xfs_bmdr_rec_addr (dib,1 ), nrecs); } maxrecs =libxfs_bmdr_maxrecs (XFS_DFORK_SIZE (dip, mp, whichfork),0 );
@@ -2204,6 +2264,10 @@ process_btinode( }for (i =0 ; i < nrecs; i++) { +struct scan_bmap sbm = { + .dip = dip, + .whichfork = whichfork, + };xfs_agnumber_t ag;xfs_agblock_t bno;
@@ -2220,7 +2284,7 @@ process_btinode(continue ; } -if (!scan_btree (ag, bno, level, btype, &itype, scanfunc_bmap)) +if (!scan_btree (ag, bno, level, btype, &sbm, scanfunc_bmap))return 0 ; }return 1 ;
@@ -2229,19 +2293,13 @@ process_btinode(static int process_exinode (struct xfs_dinode *dip, -typnm_t itype) +int whichfork) { -int whichfork; -int used; -xfs_extnum_t nex, max_nex; +xfs_extnum_t max_nex =xfs_iext_max_nextents ( +xfs_dinode_has_large_extent_counts (dip), whichfork); +xfs_extnum_t nex =xfs_dfork_nextents (dip, whichfork); +int used = nex *sizeof (struct xfs_bmbt_rec ); - whichfork = (itype ==TYP_ATTR ) ?XFS_ATTR_FORK :XFS_DATA_FORK ; - - nex =xfs_dfork_nextents (dip, whichfork); - max_nex =xfs_iext_max_nextents ( -xfs_dinode_has_large_extent_counts (dip), - whichfork); - used = nex *sizeof (xfs_bmbt_rec_t);if (nex > max_nex || used >XFS_DFORK_SIZE (dip, mp, whichfork)) {if (metadump.show_warnings) print_warning("bad number of extents %llu in inode %lld",
@@ -2257,52 +2315,52 @@ process_exinode( XFS_DFORK_SIZE(dip, mp, whichfork) - used); -return process_bmbt_reclist ((xfs_bmbt_rec_t *)XFS_DFORK_PTR (dip, - whichfork), nex, itype); +return process_bmbt_reclist (dip, whichfork, + (struct xfs_bmbt_rec *)XFS_DFORK_PTR (dip, whichfork), + nex); }static int process_inode_data ( -struct xfs_dinode *dip, -typnm_t itype) +struct xfs_dinode *dip) {switch (dip->di_format) { -case XFS_DINODE_FMT_LOCAL : -if (!(metadump.obfuscate || metadump.zero_stale_data)) -break ; +case XFS_DINODE_FMT_LOCAL : +if (!(metadump.obfuscate || metadump.zero_stale_data)) +break ; -/* -* If the fork size is invalid, we can't safely do -* anything with this fork. Leave it alone to preserve -* the information for diagnostic purposes. -*/ -if (XFS_DFORK_DSIZE (dip, mp) >XFS_LITINO (mp)) { -print_warning ( +/* +* If the fork size is invalid, we can't safely do anything +* with this fork. Leave it alone to preserve the information +* for diagnostic purposes. +*/ +if (XFS_DFORK_DSIZE (dip, mp) >XFS_LITINO (mp)) { +print_warning ("Invalid data fork size (%d) in inode %llu, preserving contents!" , -XFS_DFORK_DSIZE (dip, mp), - (long long )metadump.cur_ino); -break ; - } +XFS_DFORK_DSIZE (dip, mp), + (long long )metadump.cur_ino); +break ; + } -switch (itype) { -case TYP_DIR2 : -process_sf_dir (dip); -break ; +switch (be16_to_cpu (dip->di_mode) &S_IFMT ) { +case S_IFDIR : +process_sf_dir (dip); +break ; -case TYP_SYMLINK : -process_sf_symlink (dip); -break ; +case S_IFLNK : +process_sf_symlink (dip); +break ; -default : -break ; - } +default :break ; + } +break ; -case XFS_DINODE_FMT_EXTENTS : -return process_exinode (dip, itype); +case XFS_DINODE_FMT_EXTENTS : +return process_exinode (dip,XFS_DATA_FORK ); -case XFS_DINODE_FMT_BTREE : -return process_btinode (dip, itype); +case XFS_DINODE_FMT_BTREE : +return process_btinode (dip,XFS_DATA_FORK ); }return 1 ; }
@@ -2375,28 +2433,22 @@ process_inode(/* copy appropriate data fork metadata */ switch (be16_to_cpu (dip->di_mode) &S_IFMT ) { -case S_IFDIR : - rval =process_inode_data (dip,TYP_DIR2 ); -if (dip->di_format ==XFS_DINODE_FMT_LOCAL ) - need_new_crc = true; -break ; -case S_IFLNK : - rval =process_inode_data (dip,TYP_SYMLINK ); -if (dip->di_format ==XFS_DINODE_FMT_LOCAL ) - need_new_crc = true; -break ; -case S_IFREG : - rval =process_inode_data (dip,TYP_DATA ); -break ; -case S_IFIFO : -case S_IFCHR : -case S_IFBLK : -case S_IFSOCK : -process_dev_inode (dip); +case S_IFDIR : +case S_IFLNK : +case S_IFREG : + rval =process_inode_data (dip); +if (dip->di_format ==XFS_DINODE_FMT_LOCAL ) need_new_crc = true; -break ; -default : -break ; +break ; +case S_IFIFO : +case S_IFCHR : +case S_IFBLK : +case S_IFSOCK : +process_dev_inode (dip); + need_new_crc = true; +break ; +default : +break ; }nametable_clear ();if (!rval)
@@ -2406,20 +2458,17 @@ process_inode(if (XFS_DFORK_DSIZE (dip, mp) <XFS_LITINO (mp)) { attr_data.remote_val_count =0 ;switch (dip->di_aformat) { -case XFS_DINODE_FMT_LOCAL : - need_new_crc = true; -if (metadump.obfuscate || - metadump.zero_stale_data) -process_sf_attr (dip); -break ; - -case XFS_DINODE_FMT_EXTENTS : - rval =process_exinode (dip,TYP_ATTR ); -break ; - -case XFS_DINODE_FMT_BTREE : - rval =process_btinode (dip,TYP_ATTR ); -break ; +case XFS_DINODE_FMT_LOCAL : + need_new_crc = true; +if (metadump.obfuscate || metadump.zero_stale_data) +process_sf_attr (dip); +break ; +case XFS_DINODE_FMT_EXTENTS : + rval =process_exinode (dip,XFS_ATTR_FORK ); +break ; +case XFS_DINODE_FMT_BTREE : + rval =process_btinode (dip,XFS_ATTR_FORK ); +break ; }nametable_clear (); }
@@ -2796,70 +2845,6 @@ scan_ag(return rval; } -static int -copy_ino ( -xfs_ino_t ino, -typnm_t itype) -{ -xfs_agnumber_t agno; -xfs_agblock_t agbno; -xfs_agino_t agino; -int offset; -int rval =1 ; - -if (ino ==0 || ino ==NULLFSINO ) -return 1 ; - - agno =XFS_INO_TO_AGNO (mp, ino); - agino =XFS_INO_TO_AGINO (mp, ino); - agbno =XFS_AGINO_TO_AGBNO (mp, agino); - offset =XFS_AGINO_TO_OFFSET (mp, agino); - -if (agno >= mp->m_sb.sb_agcount || agbno >= mp->m_sb.sb_agblocks || - offset >= mp->m_sb.sb_inopblock) { -if (metadump.show_warnings) -print_warning ("invalid %s inode number (%lld)" , - typtab[itype].name, (long long )ino); -return 1 ; - } - -push_cur (); -set_cur (&typtab[TYP_INODE ],XFS_AGB_TO_DADDR (mp, agno, agbno), - blkbb,DB_RING_IGN ,NULL ); -if (iocur_top->data ==NULL ) { -print_warning ("cannot read %s inode %lld" , - typtab[itype].name, (long long )ino); - rval = !metadump.stop_on_read_error; - goto pop_out; - } -off_cur (offset << mp->m_sb.sb_inodelog, mp->m_sb.sb_inodesize); - - metadump.cur_ino = ino; - rval =process_inode_data (iocur_top->data, itype); -pop_out: -pop_cur (); -return rval; -} - - -static int -copy_sb_inodes (void ) -{ -if (!copy_ino (mp->m_sb.sb_rbmino,TYP_RTBITMAP )) -return 0 ; - -if (!copy_ino (mp->m_sb.sb_rsumino,TYP_RTSUMMARY )) -return 0 ; - -if (!copy_ino (mp->m_sb.sb_uquotino,TYP_DQBLK )) -return 0 ; - -if (!copy_ino (mp->m_sb.sb_gquotino,TYP_DQBLK )) -return 0 ; - -return copy_ino (mp->m_sb.sb_pquotino,TYP_DQBLK ); -} -static int copy_log (void ) {
@@ -3296,10 +3281,6 @@ metadump_f( } } -/* copy realtime and quota inode contents */ -if (!exitcode) - exitcode = !copy_sb_inodes (); -/* copy log */ if (!exitcode && !(metadump.version ==1 && metadump.external_log)) exitcode = !copy_log ();
PATCH 12/41 xfs_db: support metadata directories in the path command
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
Teach various directory tree debugger commands to traverse the metadata directory tree by adding a -m switch to select that tree.
--- db/namei.c | 71 ++++++++++++++++++++++++++++++++++++++++++++--------- man/man8/xfs_db.8 | 23 ++++++++++++++--- 2 files changed, 78 insertions(+), 16 deletions(-)
db/namei.c +59 -12
@@ -139,11 +139,11 @@ path_navigate(/* Walk a directory path to an inode and set the io cursor to that inode. */ static int path_walk ( +xfs_ino_t rootino,char *path) {struct dirpath *dirpath;char *p = path; -xfs_ino_t rootino = mp->m_sb.sb_rootino;int error =0 ;if (*p =='/' ) {
@@ -173,6 +173,9 @@ path_help(void)dbprintf (_ ("\n" " Navigate to an inode via directory path.\n" +"\n" +" Options:\n" +" -m -- Walk an absolute path down the metadata directory tree.\n" )); }
@@ -181,18 +184,34 @@ path_f(int argc, char **argv) { + xfs_ino_t rootino = mp->m_sb.sb_rootino;int c;int error; -while ((c =getopt (argc, argv,"" )) !=-1 ) { +while ((c =getopt (argc, argv,"m" )) !=-1 ) {switch (c) { +case 'm' : +/* Absolute path, start from metadata rootdir. */ +if (!xfs_has_metadir (mp)) { +dbprintf ( +_ ("filesystem does not support metadata directories.\n" )); + exitcode =1 ; +return 0 ; + } + rootino = mp->m_sb.sb_metadirino; +break ;default :path_help ();return 0 ; } } - error =path_walk (argv[optind]); +if (argc == optind || argc > optind +1 ) { +dbprintf (_ ("Only supply one path.\n" )); +return -1 ; + } + + error =path_walk (rootino, argv[optind]);if (error) {dbprintf ("%s: %s\n" , argv[optind],strerror (error)); exitcode =1 ;
@@ -206,7 +225,7 @@ static struct cmdinfo path_cmd = { .altname = NULL, .cfunc = path_f, .argmin = 1, - .argmax = 1, + .argmax = -1, .canpush = 0, .args = "", .help = path_help,
@@ -519,6 +538,7 @@ ls_help(void)" Options:\n" " -i -- Resolve the given paths to their corresponding inode numbers.\n" " If no paths are given, display the current inode number.\n" +" -m -- Walk an absolute path down the metadata directory tree.\n" "\n" " Directory contents will be listed in the format:\n" " dir_cookie inode_number type hash name_length name\n"
@@ -530,15 +550,26 @@ ls_f(int argc, char **argv) { + xfs_ino_t rootino = mp->m_sb.sb_rootino;bool inum_only = false;int c;int error =0 ; -while ((c =getopt (argc, argv,"i" )) !=-1 ) { +while ((c =getopt (argc, argv,"im" )) !=-1 ) {switch (c) {case 'i' : inum_only = true;break ; +case 'm' : +/* Absolute path, start from metadata rootdir. */ +if (!xfs_has_metadir (mp)) { +dbprintf ( +_ ("filesystem does not support metadata directories.\n" )); + exitcode =1 ; +return 0 ; + } + rootino = mp->m_sb.sb_metadirino; +break ;default :ls_help ();return 0 ;
@@ -561,7 +592,7 @@ ls_f(for (c = optind; c < argc; c++) {push_cur (); - error =path_walk (argv[c]); + error =path_walk (rootino, argv[c]);if (error) goto err_cur;
@@ -860,11 +891,22 @@ parent_f(int argc, char **argv) { + xfs_ino_t rootino = mp->m_sb.sb_rootino;int c;int error =0 ; -while ((c =getopt (argc, argv,"" )) !=-1 ) { +while ((c =getopt (argc, argv,"m" )) !=-1 ) {switch (c) { +case 'm' : +/* Absolute path, start from metadata rootdir. */ +if (!xfs_has_metadir (mp)) { +dbprintf ( +_ ("filesystem does not support metadata directories.\n" )); + exitcode =1 ; +return 0 ; + } + rootino = mp->m_sb.sb_metadirino; +break ;default :ls_help ();return 0 ;
@@ -884,7 +926,7 @@ parent_f(for (c = optind; c < argc; c++) {push_cur (); - error =path_walk (argv[c]); + error =path_walk (rootino, argv[c]);if (error) goto err_cur;
@@ -912,7 +954,7 @@ static struct cmdinfo parent_cmd = { .argmin = 0, .argmax = -1, .canpush = 0, - .args = "[paths...]", + .args = "[-m] [paths...]", .help = parent_help, };
@@ -926,6 +968,7 @@ link_help(void)"\n" " Options:\n" " -i -- Point to this specific inode number.\n" +" -m -- Select the metadata directory tree.\n" " -p -- Point to the inode given by this path.\n" " -t -- Set the file type to this value.\n" " name -- Create this directory entry with this name.\n"
@@ -1039,11 +1082,12 @@ link_f( {xfs_ino_t child_ino =NULLFSINO ;int ftype =XFS_DIR3_FT_UNKNOWN ; +xfs_ino_t rootino = mp->m_sb.sb_rootino;unsigned int i;int c;int error =0 ; -while ((c =getopt (argc, argv,"i:p:t:" )) !=-1 ) { +while ((c =getopt (argc, argv,"i:mp:t:" )) !=-1 ) {switch (c) {case 'i' : errno =0 ;
@@ -1054,9 +1098,12 @@ link_f(return 0 ; }break ; +case 'm' : + rootino = mp->m_sb.sb_metadirino; +break ;case 'p' :push_cur (); - error =path_walk (optarg); + error =path_walk (rootino, optarg);if (error) {printf ("%s: %s\n" , optarg,strerror (error)); exitcode =1 ;
@@ -1126,7 +1173,7 @@ static struct cmdinfo link_cmd = { .argmin = 0, .argmax = -1, .canpush = 0, - .args = "[-i ino] [-p path] [-t ftype] name", + .args = "[-i ino] [-m] [-p path] [-t ftype] name", .help = link_help, };
man/man8/xfs_db.8 +19 -4
@@ -992,7 +992,7 @@ .SH COMMANDS .I label is given, the current filesystem label is printed. .TP -.BI "link [-i " ino "] [-p " path "] [-t " ftype "] name" +.BI "link [-i " ino "] [-m] [-p " path "] [-t " ftype "] name" In the current directory, create a directory entry with the given .I name pointing to a file.
@@ -1005,6 +1005,10 @@ .SH COMMANDS child file unless the .I ftype option is given. +The +.B -m +option specifies that the path lookup should be done in the metadata directory +tree. The file being targetted must not be on the iunlink list. .TP .BI "log [stop | start " filename ]
@@ -1039,7 +1043,7 @@ .SH COMMANDS between xfsprogs and the kernel, which will help when diagnosing minimum log size calculation errors. .TP -.BI "ls [\-i] [" paths "]..." +.BI "ls [\-im] [" paths "]..." List the contents of a directory. If a path resolves to a directory, the directory will be listed. If no paths are supplied and the IO cursor points at a directory inode,
@@ -1053,6 +1057,9 @@ .SH COMMANDS Resolve each of the given paths to an inode number and print that number. If no paths are given and the IO cursor points to an inode, print the inode number. +.TP +.B \-m +Absolute paths should be walked from the root of the metadata directory tree. .RE .TP .BI "metadump [\-egow] " filename
@@ -1080,18 +1087,26 @@ .SH COMMANDS .B print command. .TP -.BI "parent [" paths "]..." +.BI "parent [\-m] [" paths "]..." List the parents of a file. If a path resolves to a file, the parents of that file will be listed. If no paths are supplied and the IO cursor points at an inode, the parents of that file will be listed. +The +.B \-m +option causes absolute paths to be walked from the root of the metadata +directory tree. The output format is: inode number, inode generation, ondisk namehash, namehash, name length, name. .TP -.BI "path " dir_path +.BI "path [\-m] " dir_path Walk the directory tree to an inode using the supplied path. Absolute and relative paths are supported. +The +.B \-m +option causes absolute paths to be walked from the root of the metadata +directory tree. .TP .B pop Pop location from the stack.
PATCH 13/41 xfs_db: show the metadata root directory when dumping superblocks
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
Show the metadirino field when appropriate.
--- db/sb.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+)
db/sb.c +14 -0
@@ -50,6 +50,18 @@ sb_init(void)add_command (&version_cmd); } +/* +* Counts superblock fields that only exist when the metadata directory feature +* is enabled. +*/ +static int +metadirfld_count ( +void *obj, +int startoff) +{ +return xfs_has_metadir (mp) ?1 :0 ; +} +#define OFF (f) bitize(offsetof(struct xfs_dsb, sb_ ## f))#define SZC (f) szcount(struct xfs_dsb, sb_ ## f)const field_t sb_flds[] = {
@@ -113,6 +125,8 @@ const field_t sb_flds[] = { { "pquotino", FLDT_INO, OI(OFF(pquotino)), C1, 0, TYP_INODE }, { "lsn", FLDT_UINT64X, OI(OFF(lsn)), C1, 0, TYP_NONE }, { "meta_uuid", FLDT_UUID, OI(OFF(meta_uuid)), C1, 0, TYP_NONE }, + { "metadirino", FLDT_INO, OI(OFF(metadirino)), metadirfld_count, + FLD_COUNT, TYP_INODE }, { NULL } };
PATCH 14/41 xfs_db: display di_metatype
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
Print the metadata file type if available.
--- db/field.c | 2 + db/field.h | 1 + db/inode.c | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++++------- db/inode.h | 2 + 4 files changed, 78 insertions(+), 10 deletions(-)
db/field.c +2 -0
@@ -212,6 +212,8 @@ const ftattr_t ftattrtab[] = { SI(bitsz(struct xfs_dinode)), 0, NULL, inode_core_flds }, { FLDT_DINODE_FMT, "dinode_fmt", fp_dinode_fmt, NULL, SI(bitsz(int8_t)), 0, NULL, NULL }, + { FLDT_DINODE_METATYPE, "metatype", fp_metatype, NULL, + SI(bitsz(uint16_t)), 0, NULL, NULL }, { FLDT_DINODE_U, "dinode_u", NULL, (char *)inode_u_flds, inode_u_size, FTARG_SIZE|FTARG_OKEMPTY, NULL, inode_u_flds }, { FLDT_DINODE_V3, "dinode_v3", NULL, (char *)inode_v3_flds,
db/field.h +1 -0
@@ -95,6 +95,7 @@ typedef enum fldt {FLDT_DINODE_A ,FLDT_DINODE_CORE ,FLDT_DINODE_FMT , +FLDT_DINODE_METATYPE ,FLDT_DINODE_U , FLDT_DINODE_V3,
db/inode.c +73 -10
127 lines not on this page · raw message
db/inode.h +2 -0
@@ -16,6 +16,8 @@ extern const struct field timestamp_flds[];extern int fp_dinode_fmt (void *obj,int bit,int count,char *fmtstr,int size,int arg,int base,int array); +int fp_metatype (void *obj,int bit,int count,char *fmtstr, +int size,int arg,int base,int array);extern int inode_a_size (void *obj,int startoff,int idx);extern void inode_init (void );extern typnm_t inode_next_type (void );
PATCH 15/41 xfs_db: drop the metadata checking code from blockget
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
Drop the check subcommand and all the metadata checking code from xfs_db. We haven't shipped xfs_check in xfsprogs in a decade and the last known user (fstests) stopped calling it back in July 2024.
--- db/check.c | 294 ----------------------------------------------------- man/man8/xfs_db.8 | 12 +- 2 files changed, 5 insertions(+), 301 deletions(-)
db/check.c +2 -292
@@ -236,14 +236,12 @@ static void check_dbmap(xfs_agnumber_t agno, xfs_agblock_t agbno, int ignore_reflink);static int check_inomap (xfs_agnumber_t agno,xfs_agblock_t agbno,xfs_extlen_t len,xfs_ino_t c_ino); -static void check_linkcounts (xfs_agnumber_t agno);static int check_range (xfs_agnumber_t agno,xfs_agblock_t agbno,xfs_extlen_t len);static void check_rdbmap (xfs_rfsblock_t bno,xfs_extlen_t len,dbm_t type);static int check_rinomap (xfs_rfsblock_t bno,xfs_extlen_t len,xfs_ino_t c_ino); -static void check_rootdir (void );static int check_rrange (xfs_rfsblock_t bno,xfs_extlen_t len); static void check_set_dbmap(xfs_agnumber_t agno, xfs_agblock_t agbno, xfs_extlen_t len,
@@ -252,11 +250,6 @@ static void check_set_dbmap(xfs_agnumber_t agno, xfs_agblock_t c_agbno);static void check_set_rdbmap (xfs_rfsblock_t bno,xfs_extlen_t len,dbm_t type1,dbm_t type2); -static void check_summary (void ); -static void checknot_dbmap (xfs_agnumber_t agno,xfs_agblock_t agbno, -xfs_extlen_t len,int typemask); -static void checknot_rdbmap (xfs_rfsblock_t bno,xfs_extlen_t len, -int typemask);static void dir_hash_add (xfs_dahash_t hash,xfs_dir2_dataptr_t addr);static void dir_hash_check (inodata_t *id,int v);
@@ -323,7 +316,6 @@ static void quota_add(xfs_dqid_t *p, xfs_dqid_t *g, xfs_dqid_t *u,static void quota_add1 (qdata_t **qt,xfs_dqid_t id,int dq,xfs_qcnt_t bc,xfs_qcnt_t ic,xfs_qcnt_t rc); -static void quota_check (char *s,qdata_t **qt);static void quota_init (void );static void scan_ag (xfs_agnumber_t agno);static void scan_freelist (xfs_agf_t *agf);
@@ -376,7 +368,7 @@ static const cmdinfo_t blockfree_cmd = {"blockfree" ,NULL , blockfree_f,0 ,0 ,0 , NULL, N_("free block usage information"), NULL };static const cmdinfo_t blockget_cmd = - {"blockget" ,"check" , blockget_f,0 ,-1 ,0 , + {"blockget" ,NULL , blockget_f,0 ,-1 ,0 ,N_ ("[-s|-v] [-n] [-t] [-b bno]... [-i ino] ..." ),N_ ("get block usage and check consistency" ),NULL }; static const cmdinfo_t blocktrash_cmd =
@@ -826,107 +818,9 @@ blockget_f( blist =NULL ; blist_size =0 ; } -if (serious_error) { +if (serious_error) exitcode =2 ; - dbprefix = oldprefix; -return 0 ; - } -if (xfs_has_metadir (mp)) { - dbprefix = oldprefix; -return 0 ; - } - -check_rootdir (); -/* -* Check that there are no blocks either -* a) unaccounted for or -* b) bno-free but not cnt-free -*/ -if (!tflag) {/* are we in test mode, faking out freespace? */ -for (agno =0 ; agno < mp->m_sb.sb_agcount; agno++) -checknot_dbmap (agno,0 , mp->m_sb.sb_agblocks, - (1 <<DBM_UNKNOWN ) | (1 <<DBM_FREE1 )); - } -for (agno =0 ; agno < mp->m_sb.sb_agcount; agno++) -check_linkcounts (agno); -if (mp->m_sb.sb_rblocks) { -checknot_rdbmap (0 , - (xfs_extlen_t)(mp->m_sb.sb_rextents * - mp->m_sb.sb_rextsize), -1 <<DBM_UNKNOWN ); -check_summary (); - } -if (mp->m_sb.sb_icount != icount) { -if (!sflag) -dbprintf (_ ("sb_icount %lld, counted %lld\n" ), - mp->m_sb.sb_icount, icount); - error++; - } -if (mp->m_sb.sb_ifree != ifree) { -if (!sflag) -dbprintf (_ ("sb_ifree %lld, counted %lld\n" ), - mp->m_sb.sb_ifree, ifree); - error++; - } -if (mp->m_sb.sb_fdblocks != fdblocks) { -if (!sflag) -dbprintf (_ ("sb_fdblocks %lld, counted %lld\n" ), - mp->m_sb.sb_fdblocks, fdblocks); - error++; - } -if (lazycount && mp->m_sb.sb_fdblocks != agf_aggr_freeblks) { -if (!sflag) -dbprintf (_ ("sb_fdblocks %lld, aggregate AGF count %lld\n" ), - mp->m_sb.sb_fdblocks, agf_aggr_freeblks); - error++; - } -if (mp->m_sb.sb_frextents != frextents) { -if (!sflag) -dbprintf (_ ("sb_frextents %lld, counted %lld\n" ), - mp->m_sb.sb_frextents, frextents); - error++; - } -if (mp->m_sb.sb_bad_features2 !=0 && - mp->m_sb.sb_bad_features2 != mp->m_sb.sb_features2) { -if (!sflag) -dbprintf (_ ("sb_features2 (0x%x) not same as " -"sb_bad_features2 (0x%x)\n" ), - mp->m_sb.sb_features2, - mp->m_sb.sb_bad_features2); - error++; - } -if ((sbversion &XFS_SB_VERSION_ATTRBIT ) && - !xfs_has_attr (mp)) { -if (!sflag) -dbprintf (_ ("sb versionnum missing attr bit %x\n" ), -XFS_SB_VERSION_ATTRBIT ); - error++; - } -if ((sbversion &XFS_SB_VERSION_QUOTABIT ) && - !xfs_has_quota (mp)) { -if (!sflag) -dbprintf (_ ("sb versionnum missing quota bit %x\n" ), -XFS_SB_VERSION_QUOTABIT ); - error++; - } -if (!(sbversion &XFS_SB_VERSION_ALIGNBIT ) && -xfs_has_align (mp)) { -if (!sflag) -dbprintf (_ ("sb versionnum extra align bit %x\n" ), -XFS_SB_VERSION_ALIGNBIT ); - error++; - } -if (qudo) -quota_check ("user" , qudata); -if (qpdo) -quota_check ("project" , qpdata); -if (qgdo) -quota_check ("group" , qgdata); -if (sbver_err > mp->m_sb.sb_agcount /2 ) -dbprintf (_ ("WARNING: this may be a newer XFS filesystem.\n" )); -if (error) - exitcode =3 ; dbprefix = oldprefix;return 0 ; }
@@ -1388,58 +1282,6 @@ check_inomap(return rval; } -static void -check_linkcounts ( -xfs_agnumber_t agno) -{ -inodata_t *ep; -inodata_t **ht; -int idx; -char *path; - - ht = inodata[agno]; -for (idx =0 ; idx < inodata_hash_size; ht++, idx++) { - ep = *ht; -while (ep) { -if (ep->link_set != ep->link_add || ep->link_set ==0 ) { - path =inode_name (ep->ino,NULL ); -if (!path && ep->link_add) - path =xstrdup ("?" ); -if (!sflag || ep->ilist) { -if (ep->link_add) -dbprintf (_ ("link count mismatch " -"for inode %lld (name " -"%s), nlink %d, " -"counted %d\n" ), - ep->ino, path, - ep->link_set, - ep->link_add); -else if (ep->link_set) -dbprintf (_ ("disconnected inode " -"%lld, nlink %d\n" ), - ep->ino, ep->link_set); -else -dbprintf (_ ("allocated inode %lld " -"has 0 link count\n" ), - ep->ino); - } -if (path) -xfree (path); - error++; - }else if (verbose || ep->ilist) { - path =inode_name (ep->ino,NULL ); -if (path) { -dbprintf (_ ("inode %lld name %s\n" ), - ep->ino, path); -xfree (path); - } - } - ep = ep->next; - } - } - -} - static int check_range( xfs_agnumber_t agno,
@@ -1556,25 +1398,6 @@ check_rinomap(return rval; } -static void -check_rootdir (void ) -{ -inodata_t *id; - - id =find_inode (mp->m_sb.sb_rootino,0 ); -if (id ==NULL ) { -if (!sflag) -dbprintf (_ ("root inode %lld is missing\n" ), - mp->m_sb.sb_rootino); - error++; - }else if (!id->isdir) { -if (!sflag || id->ilist) -dbprintf (_ ("root inode %lld is not a directory\n" ), - mp->m_sb.sb_rootino); - error++; - } -} - static inline void report_rrange( xfs_rfsblock_t low,
@@ -1718,77 +1541,6 @@ get_suminfo(return raw->old; } -static void -check_summary (void ) -{ -xfs_rfsblock_t bno; -union xfs_suminfo_raw *csp; -union xfs_suminfo_raw *fsp; -int log; - - csp = sumcompute; - fsp = sumfile; -for (log =0 ; log < mp->m_rsumlevels; log++) { -for (bno =0 ; - bno < mp->m_sb.sb_rbmblocks; - bno++, csp++, fsp++) { -if (csp->old != fsp->old) { -if (!sflag) -dbprintf (_ ("rt summary mismatch, size %d " -"block %llu, file: %d, " -"computed: %d\n" ), - log, bno, -get_suminfo (mp, fsp), -get_suminfo (mp, csp)); - error++; - } - } - } -} - -static void -checknot_dbmap ( -xfs_agnumber_t agno, -xfs_agblock_t agbno, -xfs_extlen_t len, -int typemask) -{ -xfs_extlen_t i; -char *p; - -if (!check_range (agno, agbno, len)) -return ; -for (i =0 , p = &dbmap[agno][agbno]; i < len; i++, p++) { -if ((1 << *p) & typemask) { -if (!sflag ||CHECK_BLISTA (agno, agbno + i)) -dbprintf (_ ("block %u/%u type %s not expected\n" ), - agno, agbno + i, typename[(dbm_t)*p]); - error++; - } - } -} - -static void -checknot_rdbmap ( -xfs_rfsblock_t bno, -xfs_extlen_t len, -int typemask) -{ -xfs_extlen_t i; -char *p; - -if (!check_rrange (bno, len)) -return ; -for (i =0 , p = &dbmap[mp->m_sb.sb_agcount][bno]; i < len; i++, p++) { -if ((1 << *p) & typemask) { -if (!sflag ||CHECK_BLIST (bno + i)) -dbprintf (_ ("rtblock %llu type %s not expected\n" ), - bno + i, typename[(dbm_t)*p]); - error++; - } - } -} - static void dir_hash_add( xfs_dahash_t hash,
@@ -3923,48 +3675,6 @@ quota_add1( qt[qh] = qe; } -static void -quota_check ( -char *s, -qdata_t **qt) -{ -int i; -qdata_t *next; -qdata_t *qp; - -for (i =0 ; i <QDATA_HASH_SIZE ; i++) { - qp = qt[i]; -while (qp) { - next = qp->next; -if (qp->count.bc != qp->dq.bc || - qp->count.ic != qp->dq.ic || - qp->count.rc != qp->dq.rc) { -if (!sflag) { -dbprintf (_ ("%s quota id %u, have/exp" ), - s, qp->id); -if (qp->count.bc != qp->dq.bc) -dbprintf (_ (" bc %lld/%lld" ), - qp->dq.bc, - qp->count.bc); -if (qp->count.ic != qp->dq.ic) -dbprintf (_ (" ic %lld/%lld" ), - qp->dq.ic, - qp->count.ic); -if (qp->count.rc != qp->dq.rc) -dbprintf (_ (" rc %lld/%lld" ), - qp->dq.rc, - qp->count.rc); -dbprintf ("\n" ); - } - error++; - } -xfree (qp); - qp = next; - } - } -xfree (qt); -} -static void quota_init (void ) {
man/man8/xfs_db.8 +3 -9
@@ -345,7 +345,7 @@ .SH COMMANDS command can be given, presumably with different arguments than the previous one. .TP .BI "blockget [\-npvs] [\-b " bno "] ... [\-i " ino "] ..." -Get block usage and check filesystem consistency. +Get block usage. The information is saved for use by a subsequent .BR blockuse ", " ncheck ", or " blocktrash command.
@@ -564,11 +564,6 @@ .SH COMMANDS half full. .RE .TP -.B check -See the -.B blockget -command. -.TP .BI "convert " "type number" " [" "type number" "] ... " type Convert from one address form to another. The known
@@ -2635,8 +2630,7 @@ .SH TYPES and printable ASCII chars. .SH DIAGNOSTICS Many messages can come from the -.B check -.RB ( blockget ) +.B blockget command. If the filesystem is completely corrupt, a core dump might be produced instead of the message
@@ -2646,7 +2640,7 @@ .SH DIAGNOSTICS .RE .PP If the filesystem is very large (has many files) then -.B check +.B blockget might run out of memory. In this case the message .RS .B out of memory
PATCH 16/41 xfs_io: support flag for limited bulkstat of the metadata directory
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
Support the new XFS_BULK_IREQ_METADIR flag for bulkstat commands.
--- io/bulkstat.c | 16 +++++++++++++++- man/man8/xfs_io.8 | 10 +++++++--- 2 files changed, 22 insertions(+), 4 deletions(-)
io/bulkstat.c +15 -1
@@ -70,6 +70,7 @@ bulkstat_help(void)" -d Print debugging output.\n" " -q Be quiet, no output.\n" " -e <ino> Stop after this inode.\n" +" -m Include metadata directories.\n" " -n <nr> Ask for this many results at once.\n" " -s <ino> Inode to start with.\n" " -v <ver> Use this version of the ioctl (1 or 5).\n"));
@@ -107,11 +108,12 @@ bulkstat_f(bool has_agno = false;bool debug = false;bool quiet = false; +bool metadir = false;unsigned int i;int c;int ret; -while ((c =getopt (argc, argv,"a:de:n:qs:v:" )) !=-1 ) { +while ((c =getopt (argc, argv,"a:de:mn:qs:v:" )) !=-1 ) {switch (c) {case 'a' : agno =cvt_u32 (optarg,10 );
@@ -131,6 +133,9 @@ bulkstat_f(return 1 ; }break ; +case 'm' : + metadir = true; +break ;case 'n' : batch_size =cvt_u32 (optarg,10 );if (errno) {
@@ -185,6 +190,8 @@ bulkstat_f(if (has_agno)xfrog_bulkstat_set_ag (breq, agno); +if (metadir) + breq->hdr.flags |=XFS_BULK_IREQ_METADIR ;set_xfd_flags (&xfd, ver);
@@ -253,6 +260,7 @@ bulkstat_single_f(unsigned long ver =0 ;unsigned int i;bool debug = false; +bool metadir = false;int c;int ret;
@@ -261,6 +269,9 @@ bulkstat_single_f(case 'd' : debug = true;break ; +case 'm' : + metadir = true; +break ;case 'v' : errno =0 ; ver =strtoull (optarg,NULL ,10 );
@@ -313,6 +324,9 @@ bulkstat_single_f( } } +if (metadir) + flags |=XFS_BULK_IREQ_METADIR ; + ret = -xfrog_bulkstat_single (&xfd, ino, flags, &bulkstat);if (ret) {xfrog_perror (ret,"xfrog_bulkstat_single" );
man/man8/xfs_io.8 +7 -3
@@ -1243,7 +1243,7 @@ .SH MEMORY MAPPED I/O COMMANDS .SH FILESYSTEM COMMANDS .TP -.BI "bulkstat [ \-a " agno " ] [ \-d ] [ \-e " endino " ] [ \-n " batchsize " ] [ \-q ] [ \-s " startino " ] [ \-v " version" ] +.BI "bulkstat [ \-a " agno " ] [ \-d ] [ \-e " endino " ] [ \-m ] [ \-n " batchsize " ] [ \-q ] [ \-s " startino " ] [ \-v " version" ] Display raw stat information about a bunch of inodes in an XFS filesystem. Options are as follows: .RS 1.0i
@@ -1260,6 +1260,9 @@ .SH FILESYSTEM COMMANDS Stop displaying records when this inode number is reached. Defaults to stopping when the system call stops returning results. .TP +.BI \-m +Include metadata directories in the output. +.TP .BI \-n " batchsize" Retrieve at most this many records per call. Defaults to 4,096.
@@ -1280,10 +1283,11 @@ .SH FILESYSTEM COMMANDS .RE .PD .TP -.BI "bulkstat_single [ \-d ] [ \-v " version " ] [ " inum... " | " special... " ] +.BI "bulkstat_single [ \-d ] [ \-m ] [ \-v " version " ] [ " inum... " | " special... " ] Display raw stat information about individual inodes in an XFS filesystem. The -.B \-d +.BR \-d , +.BR \-m , and .B \-v options are the same as the
PATCH 17/41 xfs_io: support scrubbing metadata directory paths
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
Support invoking the metadata directory path scrubber from xfs_io for testing.
--- io/scrub.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++-- man/man8/xfs_io.8 | 3 ++- 2 files changed, 62 insertions(+), 3 deletions(-)
io/scrub.c +60 -2
@@ -41,6 +41,12 @@ scrub_help(void) " Known metadata scrub types are:"));for (i =0 , d = xfrog_scrubbers; i <XFS_SCRUB_TYPE_NR ; i++, d++)printf (" %s" , d->name); +printf (_ ( +"\n" +"\n" +" Known metapath scrub arguments are:" )); +for (i =0 , d = xfrog_metapaths; i <XFS_SCRUB_METAPATH_NR ; i++, d++) +printf (" %s" , d->name);printf ("\n" ); }
@@ -125,6 +131,40 @@ parse_none(return true; } +static bool +parse_metapath ( +int argc, +char **argv, +int optind, +__u64 *ino) +{ +char *p; +unsigned long long control; +int i; + +if (optind != argc -1 ) { +fprintf (stderr,_ ("Must specify metapath number.\n" )); +return false; + } + +for (i =0 ; i <XFS_SCRUB_METAPATH_NR ; i++) { +if (!strcmp (argv[optind], xfrog_metapaths[i].name)) { + *ino = i; +return true; + } + } + + control =strtoll (argv[optind], &p,0 ); +if (*p !='\0' ) { +fprintf (stderr,_ ("Bad metapath number '%s'.\n" ), + argv[optind]); +return false; + } + + *ino = control; +return true; +} + static int parse_args( int argc,
@@ -170,6 +210,12 @@ parse_args( meta->sm_flags = flags;switch (d->group) { +case XFROG_SCRUB_GROUP_METAPATH : +if (!parse_metapath (argc, argv, optind, &meta->sm_ino)) { + exitcode =1 ; +return command_usage (cmdinfo); + } +break ;case XFROG_SCRUB_GROUP_INODE :if (!parse_inode (argc, argv, optind, &meta->sm_ino, &meta->sm_gen)) {
@@ -244,7 +290,7 @@ scrub_init(void) scrub_cmd.argmin =1 ; scrub_cmd.argmax =-1 ; scrub_cmd.flags =CMD_NOMAP_OK ; - scrub_cmd.args =_ ("type [agno|ino gen]" ); + scrub_cmd.args =_ ("type [agno|ino gen|metapath]" ); scrub_cmd.oneline =_ ("scrubs filesystem metadata" ); scrub_cmd.help = scrub_help;
@@ -275,6 +321,12 @@ repair_help(void) " Known metadata repair types are:"));for (i =0 , d = xfrog_scrubbers; i <XFS_SCRUB_TYPE_NR ; i++, d++)printf (" %s" , d->name); +printf (_ ( +"\n" +"\n" +" Known metapath repair arguments are:" )); +for (i =0 , d = xfrog_metapaths; i <XFS_SCRUB_METAPATH_NR ; i++, d++) +printf (" %s" , d->name);printf ("\n" ); }
@@ -327,7 +379,7 @@ repair_init(void) repair_cmd.argmin =1 ; repair_cmd.argmax =-1 ; repair_cmd.flags =CMD_NOMAP_OK ; - repair_cmd.args =_ ("type [agno|ino gen]" ); + repair_cmd.args =_ ("type [agno|ino gen|metapath]" ); repair_cmd.oneline =_ ("repairs filesystem metadata" ); repair_cmd.help = repair_help;
@@ -495,6 +547,12 @@ scrubv_f( optind++;switch (group) { +case XFROG_SCRUB_GROUP_METAPATH : +if (!parse_metapath (argc, argv, optind, &scrubv.head.svh_ino)) { + exitcode =1 ; +return command_usage (&scrubv_cmd); + } +break ;case XFROG_SCRUB_GROUP_INODE :if (!parse_inode (argc, argv, optind, &scrubv.head.svh_ino, &scrubv.head.svh_gen)) {
man/man8/xfs_io.8 +2 -1
@@ -1425,13 +1425,14 @@ .SH FILESYSTEM COMMANDS .RE .PD .TP -.BI "scrub " type " [ " agnumber " | " "ino" " " "gen" " ]" +.BI "scrub " type " [ " agnumber " | " "ino" " " "gen" " | " metapath " ]" Scrub internal XFS filesystem metadata. The .BI type parameter specifies which type of metadata to scrub. For AG metadata, one AG number must be specified. For file metadata, the scrub is applied to the open file unless the inode number and generation number are specified. +For metapath, the name of a file or a raw number must be specified. .RE .PD .TP
PATCH 18/41 xfs_spaceman: report health of metadir inodes too
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
If the filesystem has a metadata directory tree, we should include those inodes in the health report.
--- spaceman/health.c | 2 ++ 1 file changed, 2 insertions(+)
spaceman/health.c +2 -0
@@ -324,6 +324,8 @@ report_bulkstat_health(if (agno !=NULLAGNUMBER )xfrog_bulkstat_set_ag (breq, agno); +if (file->xfd.fsgeom.flags &XFS_FSOP_GEOM_FLAGS_METADIR ) + breq->hdr.flags |=XFS_BULK_IREQ_METADIR ; do { error = -xfrog_bulkstat(&file->xfd, breq);
PATCH 19/41 xfs_scrub: tread zero-length read verify as an IO error
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
While doing some chaos testing on the xfs_scrub read verify code, I noticed that if the device under a live filesystem gets resized while scrub is running a media scan, reads will start returning 0. This causes read_verify() to run around in an infinite loop instead of erroring out like it should.
--- scrub/phase6.c | 22 ++++++++++++++++++++++ scrub/read_verify.c | 8 ++++++++ 2 files changed, 30 insertions(+)
scrub/phase6.c +22 -0
@@ -44,6 +44,9 @@ struct media_verify_state {struct read_verify_pool *rvp_realtime;struct bitmap *d_bad;/* bytes */ struct bitmap *r_bad;/* bytes */ + bool d_trunc:1; + bool r_trunc:1; + bool l_trunc:1; };/* Find the fd for a given device identifier. */
@@ -544,6 +547,13 @@ report_all_media_errors( {int ret; +if (vs->d_trunc) +str_corrupt (ctx, ctx->mntpoint,_ ("data device truncated" )); +if (vs->l_trunc) +str_corrupt (ctx, ctx->mntpoint,_ ("log device truncated" )); +if (vs->r_trunc) +str_corrupt (ctx, ctx->mntpoint,_ ("rt device truncated" )); + ret =report_disk_ioerrs (ctx, ctx->datadev, vs);if (ret) {str_liberror (ctx, ret,_ ("walking datadev io errors" ));
@@ -663,6 +673,18 @@ remember_ioerr(struct bitmap *tree;int ret; +if (!length) { +dev_t dev =disk_to_dev (ctx, disk); + +if (dev == ctx->fsinfo.fs_datadev) + vs->d_trunc = true; +else if (dev == ctx->fsinfo.fs_rtdev) + vs->r_trunc = true; +else if (dev == ctx->fsinfo.fs_logdev) + vs->l_trunc = true; +return ; + } + tree =bitmap_for_disk (ctx, disk, vs);if (!tree) {str_liberror (ctx,ENOENT ,_ ("finding bad block bitmap" ));
scrub/read_verify.c +8 -0
@@ -245,6 +245,14 @@ read_verify( read_error); rvp->ioerr_fn (rvp->ctx, rvp->disk, rv->io_start, sz, read_error, rv->io_end_arg); + }else if (sz ==0 ) { +/* No bytes at all? Did we hit the end of the disk? */ +dbg_printf ("EOF %d @ %" PRIu64" %zu err %d\n" , + rvp->disk->d_fd, rv->io_start, sz, + read_error); + rvp->ioerr_fn (rvp->ctx, rvp->disk, rv->io_start, sz, + read_error, rv->io_end_arg); +break ; }else if (sz < len) {/* * A short direct read suggests that we might have hit
PATCH 20/41 xfs_scrub: scan metadata directories during phase 3
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
Scan metadata directories for correctness during phase 3.
--- scrub/inodes.c | 11 ++++++++++- scrub/inodes.h | 5 ++++- scrub/phase3.c | 7 ++++++- scrub/phase5.c | 5 ++++- scrub/phase6.c | 2 +- 5 files changed, 25 insertions(+), 5 deletions(-)
scrub/inodes.c +10 -1
@@ -56,6 +56,7 @@ bulkstat_for_inumbers( {struct xfs_bulkstat *bstat = breq->bulkstat;struct xfs_bulkstat *bs; +unsigned int flags =0 ;int i;int error;
@@ -70,6 +71,9 @@ bulkstat_for_inumbers( strerror_r(error, errbuf, DESCR_BUFSZ)); } +if (breq->hdr.flags &XFS_BULK_IREQ_METADIR ) + flags |=XFS_BULK_IREQ_METADIR ; +/* * Check each of the stats we got back to make sure we got the inodes * we asked for.
@@ -84,7 +88,7 @@ bulkstat_for_inumbers(/* Load the one inode. */ error = -xfrog_bulkstat_single (&ctx->mnt, - inumbers->xi_startino + i,0 , bs); + inumbers->xi_startino + i, flags, bs);if (error || bs->bs_ino != inumbers->xi_startino + i) {memset (bs,0 ,sizeof (struct xfs_bulkstat )); bs->bs_ino = inumbers->xi_startino + i;
@@ -100,6 +104,7 @@ struct scan_inodes {scrub_inode_iter_fn fn;void *arg;unsigned int nr_threads; +unsigned int flags;bool aborted; };
@@ -158,6 +163,8 @@ alloc_ichunk( breq =ichunk_to_bulkstat (ichunk); breq->hdr.icount =LIBFROG_BULKSTAT_CHUNKSIZE ; +if (si->flags &SCRUB_SCAN_METADIR ) + breq->hdr.flags |=XFS_BULK_IREQ_METADIR ; *ichunkp = ichunk;return 0 ;
@@ -380,10 +387,12 @@ intscrub_scan_all_inodes ( struct scrub_ctx *ctx, scrub_inode_iter_fn fn, + unsigned int flags, void *arg) { struct scan_inodes si = { .fn = fn, + .flags = flags, .arg = arg, .nr_threads =scrub_nproc_workqueue (ctx), };
scrub/inodes.h +4 -1
@@ -17,8 +17,11 @@typedef int (*scrub_inode_iter_fn )(struct scrub_ctx *ctx,struct xfs_handle *handle,struct xfs_bulkstat *bs,void *arg); +/* Return metadata directories too. */ +#define SCRUB_SCAN_METADIR (1 << 0) +int scrub_scan_all_inodes (struct scrub_ctx *ctx,scrub_inode_iter_fn fn, -void *arg); +unsigned int flags,void *arg);int scrub_open_handle (struct xfs_handle *handle);
scrub/phase3.c +6 -1
@@ -312,6 +312,7 @@ phase3_func(struct scrub_inode_ctx ictx = { .ctx = ctx };uint64_t val;xfs_agnumber_t agno; +unsigned int scan_flags =0 ;int err; err = -ptvar_alloc(scrub_nproc(ctx), sizeof(struct action_list),
@@ -328,6 +329,10 @@ phase3_func( goto out_ptvar; } +/* Scan the metadata directory tree too. */ +if (ctx->mnt.fsgeom.flags &XFS_FSOP_GEOM_FLAGS_METADIR ) + scan_flags |=SCRUB_SCAN_METADIR ; +/* * If we already have ag/fs metadata to repair from previous phases, * we would rather not try to repair file metadata until we've tried
@@ -338,7 +343,7 @@ phase3_func( ictx.always_defer_repairs = true; } - err =scrub_scan_all_inodes (ctx, scrub_inode, &ictx); + err =scrub_scan_all_inodes (ctx, scrub_inode, scan_flags, &ictx);if (!err && ictx.aborted) err =ECANCELED ;if (err)
scrub/phase5.c +4 -1
@@ -462,6 +462,9 @@ retry_deferred_inode(unsigned int flags =0 ;int error; +if (ctx->mnt.fsgeom.flags &XFS_FSOP_GEOM_FLAGS_METADIR ) + flags |=XFS_BULK_IREQ_METADIR ; + error = -xfrog_bulkstat_single (&ctx->mnt, ino, flags, &bstat);if (error ==ENOENT ) {/* Directory is gone, mark it clear. */
@@ -772,7 +775,7 @@ _("Filesystem has errors, skipping connectivity checks."));pthread_mutex_init (&ncs.lock,NULL ); - ret =scrub_scan_all_inodes (ctx, check_inode_names, &ncs); + ret =scrub_scan_all_inodes (ctx, check_inode_names,0 , &ncs);if (ret) goto out_lock;if (ncs.aborted) {
scrub/phase6.c +1 -1
@@ -578,7 +578,7 @@ report_all_media_errors( }/* Scan for unlinked files. */ -return scrub_scan_all_inodes (ctx, report_inode_loss, vs); +return scrub_scan_all_inodes (ctx, report_inode_loss,0 , vs); }/* Schedule a read-verify of a (data block) extent. */
PATCH 21/41 xfs_scrub: re-run metafile scrubbers during phase 5
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
For metadata files on a metadir filesystem, re-run the scrubbers during phase 5 to ensure that the metadata files are still connected.
--- scrub/phase5.c | 97 +++++++++++++++++++++++++++++++++++++++++++++++++++++++- scrub/scrub.h | 7 ++++ 2 files changed, 103 insertions(+), 1 deletion(-)
scrub/phase5.c +96 -1
@@ -745,6 +745,87 @@ run_kernel_fs_scan_scrubbers(return ret; } +/* Queue one metapath scrubber. */ +static int +queue_metapath_scan ( +struct workqueue *wq, +bool *abortedp, +uint64_t type) +{ +struct fs_scan_item *item; +struct scrub_ctx *ctx = wq->wq_ctx; +int ret; + + item =malloc (sizeof (struct fs_scan_item )); +if (!item) { + ret =ENOMEM ; +str_liberror (ctx, ret,_ ("setting up metapath scan" )); +return ret; + } +scrub_item_init_metapath (&item->sri, type); +scrub_item_schedule (&item->sri,XFS_SCRUB_TYPE_METAPATH ); + item->abortedp = abortedp; + + ret = -workqueue_add (wq, fs_scan_worker,0 , item); +if (ret) +str_liberror (ctx, ret,_ ("queuing metapath scan work" )); + +return ret; +} + +/* +* Scrub metadata directory file paths to ensure that fs metadata are still +* connected where the fs needs to find them. +*/ +static int +run_kernel_metadir_path_scrubbers ( +struct scrub_ctx *ctx) +{ +struct workqueue wq; +const struct xfrog_scrub_descr *sc; +uint64_t type; +unsigned int nr_threads =scrub_nproc_workqueue (ctx); +bool aborted = false; +int ret, ret2; + + ret = -workqueue_create (&wq, (struct xfs_mount *)ctx, nr_threads); +if (ret) { +str_liberror (ctx, ret,_ ("setting up metapath scan workqueue" )); +return ret; + } + +/* +* Scan all the metadata files in parallel if metadata directories +* are enabled, because the phase 3 scrubbers might have taken out +* parts of the metadir tree. +*/ +for (type =0 ; type <XFS_SCRUB_METAPATH_NR ; type++) { + sc = &xfrog_metapaths[type]; +if (sc->group !=XFROG_SCRUB_GROUP_FS ) +continue ; + + ret =queue_metapath_scan (&wq, &aborted, type); +if (ret) { +str_liberror (ctx, ret, +_ ("queueing metapath scrub work" )); + goto wait; + } + } + +wait: + ret2 = -workqueue_terminate (&wq); +if (ret2) { +str_liberror (ctx, ret2,_ ("joining metapath scan workqueue" )); +if (!ret) + ret = ret2; + } +if (aborted && !ret) + ret =ECANCELED ; + +workqueue_destroy (&wq); +return ret; +} +/* Check directory connectivity. */ int phase5_func(
@@ -753,6 +834,16 @@ phase5_func(struct ncheck_state ncs = { .ctx = ctx };int ret; +/* +* Make sure metadata files are still connected to the metadata +* directory tree now that phase 3 pruned all corrupt directory tree +* links. +*/ +if (ctx->mnt.fsgeom.flags &XFS_FSOP_GEOM_FLAGS_METADIR ) { + ret =run_kernel_metadir_path_scrubbers (ctx); +if (ret) +return ret; + }/* * Check and fix anything that requires a full filesystem scan. We do
@@ -805,8 +896,12 @@ phase5_estimate(unsigned int *nr_threads, int *rshift) { + unsigned int scans = 2; + *items =scrub_estimate_iscan_work (ctx); - *nr_threads =scrub_nproc (ctx) *2 ; +if (ctx->mnt.fsgeom.flags &XFS_FSOP_GEOM_FLAGS_METADIR ) + scans++; + *nr_threads =scrub_nproc (ctx) * scans; *rshift =0 ;return 0 ; }
scrub/scrub.h +7 -0
@@ -108,6 +108,13 @@ scrub_item_init_file(struct scrub_item *sri, const struct xfs_bulkstat *bstat) sri->sri_gen = bstat->bs_gen; } +static inline void +scrub_item_init_metapath (struct scrub_item *sri,uint64_t metapath) +{ +memset (sri,0 ,sizeof (*sri)); + sri->sri_ino = metapath; +} +void scrub_item_dump (struct scrub_item *sri,unsigned int group_mask,const char *tag);
PATCH 22/41 xfs_repair: handle sb_metadirino correctly when zeroing supers
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
The metadata directory root inumber is now the last field in the superblock, so extend the zeroing code to know about that.
--- repair/agheader.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-)
repair/agheader.c +10 -1
@@ -319,6 +319,12 @@ check_v5_feature_mismatch(return XR_AG_SB_SEC ; } +static inline bool xfs_sb_version_hasmetadir (const struct xfs_sb *sbp) +{ +return xfs_sb_is_v5 (sbp) && + (sbp->sb_features_incompat &XFS_SB_FEAT_INCOMPAT_METADIR ); +} +/* * Possible fields that may have been set at mkfs time, * sb_inoalignmt, sb_unit, sb_width and sb_dirblklog.
@@ -357,7 +363,10 @@ secondary_sb_whack(* * size is the size of data which is valid for this sb. */ -if (xfs_sb_version_hasmetauuid (sb)) +if (xfs_sb_version_hasmetadir (sb)) + size = offsetof(struct xfs_dsb , sb_metadirino) + +sizeof (sb->sb_metadirino); +else if (xfs_sb_version_hasmetauuid (sb)) size = offsetof(struct xfs_dsb , sb_meta_uuid) +sizeof (sb->sb_meta_uuid);else if (xfs_sb_version_hascrc (sb))
PATCH 23/41 xfs_repair: dont check metadata directory dirent inumbers
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
Phase 6 always rebuilds the entire metadata directory tree, and repair quietly ignores all the DIFLAG2_METADATA directory inodes that it finds. As a result, none of the metadata directories are marked inuse in the incore data. Therefore, the is_inode_free checks are not valid for anything we find in a metadata directory.
Therefore, avoid checking is_inode_free when scanning metadata directory dirents.
--- libxfs/libxfs_api_defs.h | 1 + repair/dir2.c | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+)
libxfs/libxfs_api_defs.h +1 -0
@@ -121,6 +121,7 @@#define xfs_dinode_calc_crc libxfs_dinode_calc_crc#define xfs_dinode_good_version libxfs_dinode_good_version#define xfs_dinode_verify libxfs_dinode_verify +#define xfs_dinode_verify_metadir libxfs_dinode_verify_metadir#define xfs_dir2_data_bestfree_p libxfs_dir2_data_bestfree_p#define xfs_dir2_data_entry_tag_p libxfs_dir2_data_entry_tag_p
repair/dir2.c +35 -0
@@ -136,6 +136,29 @@ process_sf_dir2_fixoff( } } +static inline bool +is_metadata_directory ( +struct xfs_mount *mp, +struct xfs_dinode *dip) +{ +xfs_failaddr_t fa; +uint16_t mode; +uint16_t flags; +uint64_t flags2; + +if (!xfs_has_metadir (mp)) +return false; +if (dip->di_version <3 || + !(dip->di_flags2 &cpu_to_be64 (XFS_DIFLAG2_METADATA ))) +return false; + + mode =be16_to_cpu (dip->di_mode); + flags =be16_to_cpu (dip->di_flags); + flags2 =be64_to_cpu (dip->di_flags2); + fa =libxfs_dinode_verify_metadir (mp, dip, mode, flags, flags2); +return fa ==NULL ; +} +/* * this routine performs inode discovery and tries to fix things * in place. available redundancy -- inode data size should match
@@ -227,6 +250,12 @@ process_sf_dir2( }else if (!libxfs_verify_dir_ino (mp, lino)) { junkit =1 ; junkreason =_ ("invalid" ); + }else if (is_metadata_directory (mp, dip)) { +/* +* Metadata directories are always rebuilt, so don't +* bother checking if the child inode is free or not. +*/ + junkit =0 ; }else if (lino == mp->m_sb.sb_rbmino) { junkit =1 ; junkreason =_ ("realtime bitmap" );
@@ -698,6 +727,12 @@ process_dir2_data(* directory since it's still structurally intact. */ clearreason =_ ("invalid" ); + }else if (is_metadata_directory (mp, dip)) { +/* +* Metadata directories are always rebuilt, so don't +* bother checking if the child inode is free or not. +*/ + clearino =0 ; }else if (ent_ino == mp->m_sb.sb_rbmino) { clearreason =_ ("realtime bitmap" ); }else if (ent_ino == mp->m_sb.sb_rsumino) {
PATCH 24/41 xfs_repair: refactor fixing dotdot
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
Pull the code that fixes a directory's dot-dot entry into a separate helper function so that we can call it on the rootdir and (later) the metadir.
--- repair/phase6.c | 96 +++++++++++++++++++++++++++++++++---------------------- 1 file changed, 57 insertions(+), 39 deletions(-)
repair/phase6.c +57 -39
@@ -2649,6 +2649,62 @@ dir_hash_add_parent_ptrs( } } +/* +* If we have to create a .. for /, do it now *before* we delete the bogus +* entries, otherwise the directory could transform into a shortform dir which +* would probably cause the simulation to choke. Even if the illegal entries +* get shifted around, it's ok because the entries are structurally intact and +* in in hash-value order so the simulation won't get confused if it has to +* move them around. +*/ +static void +fix_dotdot ( +struct xfs_mount *mp, +xfs_ino_t ino, +struct xfs_inode *ip, +xfs_ino_t rootino, +const char *tag, +int *need_dotdot) +{ +struct xfs_trans *tp; +int nres; +int error; + +if (ino != rootino || !*need_dotdot) +return ; + +if (no_modify) { +do_warn (_ ("would recreate %s directory .. entry\n" ), tag); +return ; + } + +ASSERT (ip->i_df.if_format !=XFS_DINODE_FMT_LOCAL ); + +do_warn (_ ("recreating %s directory .. entry\n" ), tag); + + nres =libxfs_mkdir_space_res (mp,2 ); + error = -libxfs_trans_alloc (mp, &M_RES (mp)->tr_mkdir, nres,0 ,0 , &tp); +if (error) +res_failed (error); + +libxfs_trans_ijoin (tp, ip,0 ); + + error = -libxfs_dir_createname (tp, ip, &xfs_name_dotdot, ip->i_ino, + nres); +if (error) +do_error ( +_ ("can't make \"..\" entry in %s inode %" PRIu64", createname error %d\n" ), + tag ,ino, error); + +libxfs_trans_log_inode (tp, ip,XFS_ILOG_CORE ); + error = -libxfs_trans_commit (tp); +if (error) +do_error ( +_ ("%s inode \"..\" entry recreation failed (%d)\n" ), tag, error); + + *need_dotdot =0 ; +} +/* * processes all reachable inodes in directories */
@@ -2778,45 +2834,7 @@ _("error %d fixing shortform directory %llu\n"),dir_hash_add_parent_ptrs (ip, hashtab);dir_hash_done (hashtab); -/* -* if we have to create a .. for /, do it now *before* -* we delete the bogus entries, otherwise the directory -* could transform into a shortform dir which would -* probably cause the simulation to choke. Even -* if the illegal entries get shifted around, it's ok -* because the entries are structurally intact and in -* in hash-value order so the simulation won't get confused -* if it has to move them around. -*/ -if (!no_modify && need_root_dotdot && ino == mp->m_sb.sb_rootino) { -ASSERT (ip->i_df.if_format !=XFS_DINODE_FMT_LOCAL ); - -do_warn (_ ("recreating root directory .. entry\n" )); - - nres =libxfs_mkdir_space_res (mp,2 ); - error = -libxfs_trans_alloc (mp, &M_RES (mp)->tr_mkdir, - nres,0 ,0 , &tp); -if (error) -res_failed (error); - -libxfs_trans_ijoin (tp, ip,0 ); - - error = -libxfs_dir_createname (tp, ip, &xfs_name_dotdot, - ip->i_ino, nres); -if (error) -do_error ( -_ ("can't make \"..\" entry in root inode %" PRIu64", createname error %d\n" ), ino, error); - -libxfs_trans_log_inode (tp, ip,XFS_ILOG_CORE ); - error = -libxfs_trans_commit (tp); -if (error) -do_error ( -_ ("root inode \"..\" entry recreation failed (%d)\n" ), error); - - need_root_dotdot =0 ; - }else if (need_root_dotdot && ino == mp->m_sb.sb_rootino) { -do_warn (_ ("would recreate root directory .. entry\n" )); - } +fix_dotdot (mp, ino, ip, mp->m_sb.sb_rootino,"root" , &need_root_dotdot);/* * if we need to create the '.' entry, do so only if
PATCH 25/41 xfs_repair: refactor marking of metadata inodes
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
Refactor the mechanics of marking a metadata inode into a helper function so that we don't have to open-code that for every single metadata inode.
--- repair/phase6.c | 72 ++++++++++++++++++------------------------------------- 1 file changed, 24 insertions(+), 48 deletions(-)
repair/phase6.c +24 -48
@@ -2891,6 +2891,18 @@ _("error %d fixing shortform directory %llu\n"),libxfs_irele (ip); } +static void +mark_inode ( +struct xfs_mount *mp, +xfs_ino_t ino) +{ +struct ino_tree_node *irec = +find_inode_rec (mp,XFS_INO_TO_AGNO (mp, ino), +XFS_INO_TO_AGINO (mp, ino)); + +add_inode_reached (irec,XFS_INO_TO_AGINO (mp, ino) - irec->ino_startnum); +} +/* * mark realtime bitmap and summary inodes as reached. * quota inode will be marked here as well
@@ -2898,54 +2910,18 @@ _("error %d fixing shortform directory %llu\n"),static void mark_standalone_inodes (xfs_mount_t *mp) { -ino_tree_node_t *irec; -int offset; - - irec =find_inode_rec (mp,XFS_INO_TO_AGNO (mp, mp->m_sb.sb_rbmino), -XFS_INO_TO_AGINO (mp, mp->m_sb.sb_rbmino)); - - offset =XFS_INO_TO_AGINO (mp, mp->m_sb.sb_rbmino) - - irec->ino_startnum; - -add_inode_reached (irec, offset); - - irec =find_inode_rec (mp,XFS_INO_TO_AGNO (mp, mp->m_sb.sb_rsumino), -XFS_INO_TO_AGINO (mp, mp->m_sb.sb_rsumino)); - - offset =XFS_INO_TO_AGINO (mp, mp->m_sb.sb_rsumino) - - irec->ino_startnum; - -add_inode_reached (irec, offset); - -if (fs_quotas) { -if (mp->m_sb.sb_uquotino - && mp->m_sb.sb_uquotino !=NULLFSINO ) { - irec =find_inode_rec (mp,XFS_INO_TO_AGNO (mp, - mp->m_sb.sb_uquotino), -XFS_INO_TO_AGINO (mp, mp->m_sb.sb_uquotino)); - offset =XFS_INO_TO_AGINO (mp, mp->m_sb.sb_uquotino) - - irec->ino_startnum; -add_inode_reached (irec, offset); - } -if (mp->m_sb.sb_gquotino - && mp->m_sb.sb_gquotino !=NULLFSINO ) { - irec =find_inode_rec (mp,XFS_INO_TO_AGNO (mp, - mp->m_sb.sb_gquotino), -XFS_INO_TO_AGINO (mp, mp->m_sb.sb_gquotino)); - offset =XFS_INO_TO_AGINO (mp, mp->m_sb.sb_gquotino) - - irec->ino_startnum; -add_inode_reached (irec, offset); - } -if (mp->m_sb.sb_pquotino - && mp->m_sb.sb_pquotino !=NULLFSINO ) { - irec =find_inode_rec (mp,XFS_INO_TO_AGNO (mp, - mp->m_sb.sb_pquotino), -XFS_INO_TO_AGINO (mp, mp->m_sb.sb_pquotino)); - offset =XFS_INO_TO_AGINO (mp, mp->m_sb.sb_pquotino) - - irec->ino_startnum; -add_inode_reached (irec, offset); - } - } +mark_inode (mp, mp->m_sb.sb_rbmino); +mark_inode (mp, mp->m_sb.sb_rsumino); + +if (!fs_quotas) +return ; + +if (mp->m_sb.sb_uquotino && mp->m_sb.sb_uquotino !=NULLFSINO ) +mark_inode (mp, mp->m_sb.sb_uquotino); +if (mp->m_sb.sb_gquotino && mp->m_sb.sb_gquotino !=NULLFSINO ) +mark_inode (mp, mp->m_sb.sb_gquotino); +if (mp->m_sb.sb_pquotino && mp->m_sb.sb_pquotino !=NULLFSINO ) +mark_inode (mp, mp->m_sb.sb_pquotino); } static void
PATCH 26/41 xfs_repair: refactor root directory initialization
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
Refactor root directory initialization into a separate function we can call for both the root dir and the metadir.
--- repair/phase6.c | 63 +++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 40 insertions(+), 23 deletions(-)
repair/phase6.c +40 -23
@@ -587,27 +587,27 @@ mk_rsumino(xfs_mount_t *mp)libxfs_irele (ip); } -/* -* makes a new root directory. -*/ -static void -mk_root_dir (xfs_mount_t *mp) +/* Initialize a root directory. */ +static int +init_fs_root_dir ( +struct xfs_mount *mp, +xfs_ino_t ino, +mode_t mode, +struct xfs_inode **ipp) { -xfs_trans_t *tp; -xfs_inode_t *ip; -int i; -int error; -const mode_t mode =0755 ; -ino_tree_node_t *irec; +struct xfs_trans *tp; +struct xfs_inode *ip =NULL ; +struct ino_tree_node *irec; +int error; - ip =NULL ; - i = -libxfs_trans_alloc (mp, &M_RES (mp)->tr_ichange,10 ,0 ,0 , &tp); -if (i) -res_failed (i); + error = -libxfs_trans_alloc (mp, &M_RES (mp)->tr_ichange,10 ,0 ,0 , &tp); +if (error) +return error; - error = -libxfs_iget (mp, tp, mp->m_sb.sb_rootino,0 , &ip); + error = -libxfs_iget (mp, tp, ino,0 , &ip);if (error) { -do_error (_ ("could not iget root inode -- error - %d\n" ), error); +libxfs_trans_cancel (tp); +return error; }/* Reset the root directory. */
@@ -616,14 +616,31 @@ mk_root_dir(xfs_mount_t *mp) error = -libxfs_trans_commit (tp);if (error) -do_error (_ ("%s: commit failed, error %d\n" ), __func__, error); +return error; + + irec =find_inode_rec (mp,XFS_INO_TO_AGNO (mp, ino), +XFS_INO_TO_AGINO (mp, ino)); +set_inode_isadir (irec,XFS_INO_TO_AGINO (mp, ino) - irec->ino_startnum); + *ipp = ip; +return 0 ; +} + +/* +* makes a new root directory. +*/ +static void +mk_root_dir (xfs_mount_t *mp) +{ +struct xfs_inode *ip =NULL ; +int error; + + error =init_fs_root_dir (mp, mp->m_sb.sb_rootino,0755 , &ip); +if (error) +do_error ( +_ ("Could not reinitialize root directory inode, error %d\n" ), + error);libxfs_irele (ip); - - irec =find_inode_rec (mp,XFS_INO_TO_AGNO (mp, mp->m_sb.sb_rootino), -XFS_INO_TO_AGINO (mp, mp->m_sb.sb_rootino)); -set_inode_isadir (irec,XFS_INO_TO_AGINO (mp, mp->m_sb.sb_rootino) - - irec->ino_startnum); }/*
PATCH 27/41 xfs_repair: refactor grabbing realtime metadata inodes
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
Create a helper function to grab a realtime metadata inode. When metadir arrives, the bitmap and summary inodes can float, so we'll turn this function into a "load or allocate" function.
--- repair/phase6.c | 51 ++++++++++++++++++++++++++++++++++----------------- 1 file changed, 34 insertions(+), 17 deletions(-)
repair/phase6.c +34 -17
@@ -474,6 +474,24 @@ reset_sbroot_ino(libxfs_inode_init (tp, &args, ip); } +/* Load a realtime freespace metadata inode from disk and reset it. */ +static int +ensure_rtino ( +struct xfs_trans *tp, +xfs_ino_t ino, +struct xfs_inode **ipp) +{ +struct xfs_mount *mp = tp->t_mountp; +int error; + + error = -libxfs_iget (mp, tp, ino,0 , ipp); +if (error) +return error; + +reset_sbroot_ino (tp,S_IFREG , *ipp); +return 0 ; +} +static void mk_rbmino (struct xfs_mount *mp)
@@ -486,15 +504,14 @@ mk_rbmino(if (error)res_failed (error); - error = -libxfs_iget (mp, tp, mp->m_sb.sb_rbmino,0 , &ip); -if (error) { -do_error ( -_ ("couldn't iget realtime bitmap inode -- error - %d\n" ), - error); - } -/* Reset the realtime bitmap inode. */ -reset_sbroot_ino (tp,S_IFREG , ip); + error =ensure_rtino (tp, mp->m_sb.sb_rbmino, &ip); +if (error) { +do_error ( +_ ("couldn't iget realtime bitmap inode -- error - %d\n" ), + error); + } + ip->i_disk_size = mp->m_sb.sb_rbmblocks * mp->m_sb.sb_blocksize;libxfs_trans_log_inode (tp, ip,XFS_ILOG_CORE ); error = -libxfs_trans_commit (tp);
@@ -560,7 +577,8 @@ _("couldn't re-initialize realtime summary inode, error %d\n"), error); }static void -mk_rsumino (xfs_mount_t *mp) +mk_rsumino ( +struct xfs_mount *mp) {struct xfs_trans *tp;struct xfs_inode *ip;
@@ -570,15 +588,14 @@ mk_rsumino(xfs_mount_t *mp)if (error)res_failed (error); - error = -libxfs_iget (mp, tp, mp->m_sb.sb_rsumino,0 , &ip); -if (error) { -do_error ( -_ ("couldn't iget realtime summary inode -- error - %d\n" ), - error); - } -/* Reset the rt summary inode. */ -reset_sbroot_ino (tp,S_IFREG , ip); + error =ensure_rtino (tp, mp->m_sb.sb_rsumino, &ip); +if (error) { +do_error ( +_ ("couldn't iget realtime summary inode -- error - %d\n" ), + error); + } + ip->i_disk_size = mp->m_rsumblocks * mp->m_sb.sb_blocksize;libxfs_trans_log_inode (tp, ip,XFS_ILOG_CORE ); error = -libxfs_trans_commit (tp);
PATCH 28/41 xfs_repair: check metadata inode flag
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
Check whether or not the metadata inode flag is set appropriately.
--- repair/dinode.c | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+)
repair/dinode.c +41 -0
@@ -2331,6 +2331,26 @@ _("Bad extent size hint %u on inode %" PRIu64 ", "), } } +static inline bool +should_have_metadir_iflag ( +struct xfs_mount *mp, +xfs_ino_t ino) +{ +if (ino == mp->m_sb.sb_metadirino) +return true; +if (ino == mp->m_sb.sb_rbmino) +return true; +if (ino == mp->m_sb.sb_rsumino) +return true; +if (ino == mp->m_sb.sb_uquotino) +return true; +if (ino == mp->m_sb.sb_gquotino) +return true; +if (ino == mp->m_sb.sb_pquotino) +return true; +return false; +} +/* * returns 0 if the inode is ok, 1 if the inode is corrupt * check_dups can be set to 1 *only* when called by the
@@ -2680,6 +2700,27 @@ _("bad (negative) size %" PRId64 " on inode %" PRIu64 "\n"), } } +if (flags2 &XFS_DIFLAG2_METADATA ) { +xfs_failaddr_t fa; + + fa =libxfs_dinode_verify_metadir (mp, dino, di_mode, +be16_to_cpu (dino->di_flags), flags2); +if (fa) { +if (!uncertain) +do_warn ( +_ ("inode %" PRIu64" is incorrectly marked as metadata\n" ), + lino); + goto clear_bad_out; + } + }else if (xfs_has_metadir (mp) && +should_have_metadir_iflag (mp, lino)) { +if (!uncertain) +do_warn ( +_ ("inode %" PRIu64" should be marked as metadata\n" ), + lino); + goto clear_bad_out; + } +if ((flags2 &XFS_DIFLAG2_REFLINK ) && !xfs_has_reflink (mp)) {if (!uncertain) {
PATCH 29/41 xfs_repair: use libxfs_metafile_iget for quota/rt inodes
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
Use the new iget function for these metadata files so that we can check types, etc.
--- repair/phase6.c | 23 +++++++++-------------- repair/quotacheck.c | 17 ++++++++++++++--- repair/rt.c | 29 ++++++++++++++++++++++------- 3 files changed, 45 insertions(+), 24 deletions(-)
repair/phase6.c +9 -14
@@ -484,6 +484,11 @@ ensure_rtino(struct xfs_mount *mp = tp->t_mountp;int error; +/* +* Don't use metafile iget here because we're resetting sb-rooted +* inodes that live at fixed inumbers, but these inodes could be in +* an arbitrary state. +*/ error = -libxfs_iget (mp, tp, ino,0 , ipp);if (error)return error;
@@ -524,16 +529,11 @@ static voidfill_rbmino ( struct xfs_mount *mp) { -struct xfs_trans *tp;struct xfs_inode *ip;int error; - error = -libxfs_trans_alloc_rollable (mp,10 , &tp); -if (error) -res_failed (error); - - error = -libxfs_iget (mp, tp, mp->m_sb.sb_rbmino,0 , &ip); -libxfs_trans_cancel (tp); + error = -libxfs_metafile_iget (mp, mp->m_sb.sb_rbmino, +XFS_METAFILE_RTBITMAP , &ip);if (error)do_error (_ ("couldn't iget realtime bitmap inode, error %d\n" ), error);
@@ -551,16 +551,11 @@ static voidfill_rsumino ( struct xfs_mount *mp) { -struct xfs_trans *tp;struct xfs_inode *ip;int error; - error = -libxfs_trans_alloc_rollable (mp,10 , &tp); -if (error) -res_failed (error); - - error = -libxfs_iget (mp, tp, mp->m_sb.sb_rsumino,0 , &ip); -libxfs_trans_cancel (tp); + error = -libxfs_metafile_iget (mp, mp->m_sb.sb_rsumino, +XFS_METAFILE_RTSUMMARY , &ip);if (error)do_error (_ ("couldn't iget realtime summary inode, error %d\n" ), error);
repair/quotacheck.c +14 -3
@@ -403,21 +403,26 @@ quotacheck_verify(struct xfs_ifork *ifp;struct qc_dquots *dquots =NULL ;struct avl64node *node, *n; +struct xfs_trans *tp;xfs_ino_t ino =NULLFSINO ; +enum xfs_metafile_type metafile_type;int error;switch (type) {case XFS_DQTYPE_USER : ino = mp->m_sb.sb_uquotino; dquots = user_dquots; + metafile_type =XFS_METAFILE_USRQUOTA ;break ;case XFS_DQTYPE_GROUP : ino = mp->m_sb.sb_gquotino; dquots = group_dquots; + metafile_type =XFS_METAFILE_GRPQUOTA ;break ;case XFS_DQTYPE_PROJ : ino = mp->m_sb.sb_pquotino; dquots = proj_dquots; + metafile_type =XFS_METAFILE_PRJQUOTA ;break ; }
@@ -429,17 +434,21 @@ quotacheck_verify(if (!dquots || !chkd_flags)return ; - error = -libxfs_iget (mp,NULL , ino,0 , &ip); + error = -libxfs_trans_alloc_empty (mp, &tp); +if (error) +do_error (_ ("could not alloc transaction to open quota file\n" )); + + error = -libxfs_trans_metafile_iget (tp, ino, metafile_type, &ip);if (error) {do_warn (_ ("could not open %s inode %" PRIu64" for quotacheck, err=%d\n" ),qflags_typestr (type), ino, error); chkd_flags =0 ; -return ; + goto out_trans; } ifp =xfs_ifork_ptr (ip,XFS_DATA_FORK ); - error = -libxfs_iread_extents (NULL , ip,XFS_DATA_FORK ); + error = -libxfs_iread_extents (tp, ip,XFS_DATA_FORK );if (error) { do_warn( _("could not read %s inode %"PRIu64" extents, err=%d\n"),
@@ -477,6 +486,8 @@ _("%s record for id %u not found on disk (bcount %"PRIu64" rtbcount %"PRIu64" ic } err:libxfs_irele (ip); +out_trans: +libxfs_trans_cancel (tp); }/*
repair/rt.c +22 -7
@@ -144,18 +144,34 @@ generate_rtinfo(static void check_rtfile_contents (struct xfs_mount *mp, -const char *filename, -xfs_ino_t ino, -void *buf, +enum xfs_metafile_type metafile_type,xfs_fileoff_t filelen) {struct xfs_bmbt_irec map;struct xfs_buf *bp;struct xfs_inode *ip; +const char *filename; +void *buf; +xfs_ino_t ino;xfs_fileoff_t bno =0 ;int error; - error = -libxfs_iget (mp,NULL , ino,0 , &ip); +switch (metafile_type) { +case XFS_METAFILE_RTBITMAP : + ino = mp->m_sb.sb_rbmino; + filename ="rtbitmap" ; + buf = btmcompute; +break ; +case XFS_METAFILE_RTSUMMARY : + ino = mp->m_sb.sb_rsumino; + filename ="rtsummary" ; + buf = sumcompute; +break ; +default : +return ; + } + + error = -libxfs_metafile_iget (mp, ino, metafile_type, &ip);if (error) {do_warn (_ ("unable to open %s file, err %d\n" ), filename, error);return ;
@@ -216,7 +232,7 @@ check_rtbitmap(if (need_rbmino)return ; -check_rtfile_contents (mp,"rtbitmap" , mp->m_sb.sb_rbmino, btmcompute, +check_rtfile_contents (mp,XFS_METAFILE_RTBITMAP , mp->m_sb.sb_rbmblocks); }
@@ -227,6 +243,5 @@ check_rtsummary(if (need_rsumino)return ; -check_rtfile_contents (mp,"rtsummary" , mp->m_sb.sb_rsumino, sumcompute, - mp->m_rsumblocks); +check_rtfile_contents (mp,XFS_METAFILE_RTSUMMARY , mp->m_rsumblocks); }
PATCH 30/41 xfs_repair: rebuild the metadata directory
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
Check the dirents in metadata directories for problems and repair them if necessary. Also make sure that the sb-rooted inodes (root, metadir root, rt bitmap, rt summary) are always allocated in that order.
Note that xfs_repair will always rebuild the metadata directory tree itself, so we only need to report problems, not fix them.
--- libxfs/libxfs_api_defs.h | 1 repair/dino_chunks.c | 12 ++++++ repair/dir2.c | 16 +++++++- repair/globals.c | 3 + repair/globals.h | 3 + repair/incore.h | 13 ++++++ repair/phase1.c | 2 + repair/phase2.c | 53 +++++++++++++++++++------- repair/phase4.c | 16 ++++++++ repair/phase6.c | 73 ++++++++++++++++++++++++++++++++++-- repair/pptr.c | 94 ++++++++++++++++++++++++++++++++++++++++++++++ repair/pptr.h | 2 + repair/sb.c | 3 + repair/xfs_repair.c | 50 ++++++++++++++++++++++++ 14 files changed, 320 insertions(+), 21 deletions(-)
libxfs/libxfs_api_defs.h +1 -0
@@ -214,6 +214,7 @@#define xfs_metafile_iget libxfs_metafile_iget#define xfs_trans_metafile_iget libxfs_trans_metafile_iget +#define xfs_metafile_set_iflag libxfs_metafile_set_iflag#define xfs_metadir_link libxfs_metadir_link#define xfs_metadir_lookup libxfs_metadir_lookup#define xfs_metadir_start_create libxfs_metadir_start_create
repair/dino_chunks.c +12 -0
@@ -932,6 +932,18 @@ process_inode_chunk(_ ("would clear root inode %" PRIu64"\n" ), ino); } + }else if (mp->m_sb.sb_metadirino == ino) { + need_metadir_inode = true; + +if (!no_modify) { +do_warn ( +_ ("cleared metadata directory %" PRIu64"\n" ), + ino); + }else { +do_warn ( +_ ("would clear metadata directory %" PRIu64"\n" ), + ino); + } }else if (mp->m_sb.sb_rbmino == ino) { need_rbmino =1 ;
repair/dir2.c +14 -2
@@ -271,6 +271,9 @@ process_sf_dir2( }else if (lino == mp->m_sb.sb_pquotino) { junkit =1 ; junkreason =_ ("project quota" ); + }else if (lino == mp->m_sb.sb_metadirino) { + junkit =1 ; + junkreason =_ ("metadata directory root" ); }else if ((irec_p =find_inode_rec (mp,XFS_INO_TO_AGNO (mp, lino),XFS_INO_TO_AGINO (mp, lino))) !=NULL ) {
@@ -564,7 +567,8 @@ _("corrected root directory %" PRIu64 " .. entry, was %" PRIu64 ", now %" PRIu64_ ("would have corrected root directory %" PRIu64" .. entry from %" PRIu64" to %" PRIu64"\n" ), ino, *parent, ino); } - }else if (ino == *parent && ino != mp->m_sb.sb_rootino) { + }else if (ino == *parent && ino != mp->m_sb.sb_rootino && + ino != mp->m_sb.sb_metadirino) {/* * likewise, non-root directories can't have .. pointing * to .
@@ -743,6 +747,8 @@ process_dir2_data( clearreason =_ ("group quota" ); }else if (ent_ino == mp->m_sb.sb_pquotino) { clearreason =_ ("project quota" ); + }else if (ent_ino == mp->m_sb.sb_metadirino) { + clearreason =_ ("metadata directory root" ); }else { irec_p = find_inode_rec(mp, XFS_INO_TO_AGNO(mp, ent_ino),
@@ -864,7 +870,8 @@ _("entry at block %u offset %" PRIdPTR " in directory inode %" PRIu64 " has ille* NULLFSINO otherwise. */ if (ino == ent_ino && - ino != mp->m_sb.sb_rootino) { + ino != mp->m_sb.sb_rootino && + ino != mp->m_sb.sb_metadirino) { *parent =NULLFSINO ; do_warn( _("bad .. entry in directory inode %" PRIu64 ", points to self: "),
@@ -1519,9 +1526,14 @@ process_dir2( }else if (dotdot ==0 && ino == mp->m_sb.sb_rootino) {do_warn (_ ("no .. entry for root directory %" PRIu64"\n" ), ino); need_root_dotdot =1 ; + }else if (dotdot ==0 && ino == mp->m_sb.sb_metadirino) { +do_warn (_ ("no .. entry for metaino directory %" PRIu64"\n" ), ino); + need_metadir_dotdot =1 ; }ASSERT ((ino != mp->m_sb.sb_rootino && ino != *parent) || + (ino == mp->m_sb.sb_metadirino && + (ino == *parent || need_metadir_dotdot ==1 )) || (ino == mp->m_sb.sb_rootino && (ino == *parent || need_root_dotdot ==1 )));
repair/globals.c +3 -0
@@ -66,6 +66,9 @@ int fs_is_dirty;int need_root_inode;int need_root_dotdot; +bool need_metadir_inode; +int need_metadir_dotdot; +int need_rbmino;int need_rsumino;
repair/globals.h +3 -0
@@ -107,6 +107,9 @@ extern int fs_is_dirty;extern int need_root_inode;extern int need_root_dotdot; +extern bool need_metadir_inode; +extern int need_metadir_dotdot; +extern int need_rbmino;extern int need_rsumino;
repair/incore.h +13 -0
@@ -661,4 +661,17 @@ inorec_set_freecount( rp->ir_u.f.ir_freecount = cpu_to_be32(freecount); } +/* +* Number of inodes assumed to be always allocated because they are created +* by mkfs. +*/ +static inline unsigned int +xfs_rootrec_inodes_inuse ( +struct xfs_mount *mp) +{ +if (xfs_has_metadir (mp)) +return 4 ;/* sb_rootino, sb_rbmino, sb_rsumino, sb_metadirino */ +return 3 ;/* sb_rootino, sb_rbmino, sb_rsumino */ +} +#endif /* XFS_REPAIR_INCORE_H */
repair/phase1.c +2 -0
@@ -48,6 +48,8 @@ phase1(xfs_mount_t *mp) primary_sb_modified =0 ; need_root_inode =0 ; need_root_dotdot =0 ; + need_metadir_inode = false; + need_metadir_dotdot =0 ; need_rbmino =0 ; need_rsumino =0 ; lost_quotas =0 ;
repair/phase2.c +38 -15
104 lines not on this page · raw message
repair/phase4.c +16 -0
@@ -264,6 +264,22 @@ phase4(xfs_mount_t *mp)do_warn (_ ("root inode lost\n" )); } +/* +* If metadata directory trees are enabled, the metadata root directory +* always comes immediately after the regular root directory, even if +* it's free. +*/ +if (xfs_has_metadir (mp) && + (is_inode_free (irec,1 ) || !inode_isadir (irec,1 ))) { + need_metadir_inode = true; +if (no_modify) +do_warn ( +_ ("metadata directory root inode would be lost\n" )); +else +do_warn ( +_ ("metadata directory root inode lost\n" )); + } +for (i =0 ; i < mp->m_sb.sb_agcount; i++) { ag_end = (i < mp->m_sb.sb_agcount -1 ) ? mp->m_sb.sb_agblocks : mp->m_sb.sb_dblocks -
repair/phase6.c +69 -4
132 lines not on this page · raw message
repair/pptr.c +94 -0
97 lines not on this page · raw message
repair/pptr.h +2 -0
@@ -14,4 +14,6 @@ void add_parent_ptr(xfs_ino_t ino, const unsigned char *fname,void check_parent_ptrs (struct xfs_mount *mp); +void try_erase_parent_ptrs (struct xfs_inode *ip); +#endif /* __REPAIR_PPTR_H__ */
repair/sb.c +3 -0
@@ -28,6 +28,7 @@ copy_sb(xfs_sb_t *source, xfs_sb_t *dest)xfs_ino_t uquotino;xfs_ino_t gquotino;xfs_ino_t pquotino; +xfs_ino_t metadirino;uint16_t versionnum; rootino = dest->sb_rootino;
@@ -36,6 +37,7 @@ copy_sb(xfs_sb_t *source, xfs_sb_t *dest) uquotino = dest->sb_uquotino; gquotino = dest->sb_gquotino; pquotino = dest->sb_pquotino; + metadirino = dest->sb_metadirino; versionnum = dest->sb_versionnum;
@@ -47,6 +49,7 @@ copy_sb(xfs_sb_t *source, xfs_sb_t *dest) dest->sb_uquotino = uquotino; dest->sb_gquotino = gquotino; dest->sb_pquotino = pquotino; + dest->sb_metadirino = metadirino; dest->sb_versionnum = versionnum;
repair/xfs_repair.c +50 -0
62 lines not on this page · raw message
PATCH 31/41 xfs_repair: don't let metadata and regular files mix
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
Track whether or not inodes thought they were metadata inodes. We cannot allow metadata inodes to appear in the regular directory tree, and we cannot allow regular inodes to appear in the metadata directory tree.
--- repair/dinode.c | 21 +++++++++++++++++ repair/incore.h | 19 +++++++++++++++ repair/incore_ino.c | 1 + repair/phase2.c | 7 +++++- repair/phase6.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 110 insertions(+), 1 deletion(-)
repair/dinode.c +21 -0
@@ -2392,6 +2392,7 @@ process_dinode_int(struct xfs_dinode *dino = *dinop;xfs_agino_t unlinked_ino;struct xfs_perag *pag; +bool is_meta = false; *dirty = *isa_dir =0 ; *used = is_used;
@@ -2971,6 +2972,18 @@ _("Bad CoW extent size %u on inode %" PRIu64 ", "),if (collect_rmaps)record_inode_reflink_flag (mp, dino, agno, ino, lino); +/* Does this inode think it was metadata? */ +if (dino->di_version >=3 && + (dino->di_flags2 &cpu_to_be64 (XFS_DIFLAG2_METADATA ))) { +struct ino_tree_node *irec; +int off; + + irec =find_inode_rec (mp, agno, ino); + off =get_inode_offset (mp, lino, irec); +set_inode_is_meta (irec, off); + is_meta = true; + } +/* * check data fork -- if it's bad, clear the inode */
@@ -3057,6 +3070,14 @@ _("Bad CoW extent size %u on inode %" PRIu64 ", "), *used = is_free; *isa_dir =0 ;blkmap_free (dblkmap); +if (is_meta) { +struct ino_tree_node *irec; +int off; + + irec =find_inode_rec (mp, agno, ino); + off =get_inode_offset (mp, lino, irec); +clear_inode_is_meta (irec, off); + }return 1 ; }
repair/incore.h +19 -0
@@ -271,6 +271,7 @@ typedef struct ino_tree_node {uint64_t ino_isa_dir;/* bit == 1 if a directory */ uint64_t ino_was_rl;/* bit == 1 if reflink flag set */ uint64_t ino_is_rl;/* bit == 1 if reflink flag should be set */ +uint64_t ino_is_meta;/* bit == 1 if metadata */ uint8_t nlink_size;union ino_nlink disk_nlinks;/* on-disk nlinks, set in P3 */ union {
@@ -538,6 +539,24 @@ static inline int inode_is_rl(struct ino_tree_node *irec, int offset)return (irec->ino_is_rl &IREC_MASK (offset)) !=0 ; } +/* +* set/clear/test was inode marked as metadata +*/ +static inline void set_inode_is_meta (struct ino_tree_node *irec,int offset) +{ + irec->ino_is_meta |=IREC_MASK (offset); +} + +static inline void clear_inode_is_meta (struct ino_tree_node *irec,int offset) +{ + irec->ino_is_meta &= ~IREC_MASK (offset); +} + +static inline int inode_is_meta (struct ino_tree_node *irec,int offset) +{ +return (irec->ino_is_meta &IREC_MASK (offset)) !=0 ; +} +/* * add_inode_reached() is set on inode I only if I has been reached * by an inode P claiming to be the parent and if I is a directory,
repair/incore_ino.c +1 -0
@@ -257,6 +257,7 @@ alloc_ino_node( irec->ino_isa_dir =0 ; irec->ino_was_rl =0 ; irec->ino_is_rl =0 ; + irec->ino_is_meta =0 ; irec->ir_free = (xfs_inofree_t) -1 ; irec->ir_sparse =0 ; irec->ino_un.ex_data =NULL ;
repair/phase2.c +6 -1
@@ -557,8 +557,10 @@ phase2(*/ ino_rec =set_inode_used_alloc (mp,0 ,XFS_INO_TO_AGINO (mp, sb->sb_rootino)); -for (j =1 ; j < inuse; j++) +for (j =1 ; j < inuse; j++) {set_inode_used (ino_rec, j); +set_inode_is_meta (ino_rec, j); + }for (j = inuse; j <XFS_INODES_PER_CHUNK ; j++)set_inode_free (ino_rec, j);
@@ -594,6 +596,7 @@ phase2(else do_warn (_ ("would correct\n" )); } +set_inode_is_meta (ino_rec, j); j++; }
@@ -605,6 +608,7 @@ phase2(else do_warn (_ ("would correct\n" )); } +set_inode_is_meta (ino_rec, j); j++;if (is_inode_free (ino_rec, j)) {
@@ -615,6 +619,7 @@ phase2(else do_warn (_ ("would correct\n" )); } +set_inode_is_meta (ino_rec, j); j++; }
repair/phase6.c +63 -0
75 lines not on this page · raw message
PATCH 32/41 xfs_repair: update incore metadata state whenever we create new files
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
Make sure that we update our incore metadata inode bookkeepping whenever we create new metadata files. There will be many more of these later.
--- repair/phase6.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+)
repair/phase6.c +17 -0
@@ -474,6 +474,22 @@ reset_sbroot_ino(libxfs_inode_init (tp, &args, ip); } +/* +* Mark a newly allocated inode as metadata in the incore bitmap. Callers +* must have already called mark_ino_inuse to ensure there is an incore record. +*/ +static void +mark_ino_metadata ( +struct xfs_mount *mp, +xfs_ino_t ino) +{ +struct ino_tree_node *irec = +find_inode_rec (mp,XFS_INO_TO_AGNO (mp, ino), +XFS_INO_TO_AGINO (mp, ino)); + +set_inode_is_meta (irec,get_inode_offset (mp, ino, irec)); +} +/* Load a realtime freespace metadata inode from disk and reset it. */ static int ensure_rtino(
@@ -693,6 +709,7 @@ mk_metadir(libxfs_trans_ijoin (tp, mp->m_metadirip,0 );libxfs_metafile_set_iflag (tp, mp->m_metadirip,XFS_METAFILE_DIR ); +mark_ino_metadata (mp, mp->m_metadirip->i_ino); error = -libxfs_trans_commit (tp);if (error)
PATCH 33/41 xfs_repair: pass private data pointer to scan_lbtree
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
Pass a private data pointer through scan_lbtree. We'll use this later when scanning the rtrmapbt to keep track of scan state.
--- repair/dinode.c | 2 +- repair/scan.c | 11 +++++++---- repair/scan.h | 7 +++++-- 3 files changed, 13 insertions(+), 7 deletions(-)
repair/dinode.c +1 -1
@@ -839,7 +839,7 @@ _("bad bmap btree ptr 0x%" PRIx64 " in ino %" PRIu64 "\n"),if (scan_lbtree (get_unaligned_be64 (&pp[i]), level, scan_bmapbt, type, whichfork, lino, tot, nex, blkmapp, - &cursor,1 , check_dups, magic, + &cursor,1 , check_dups, magic,NULL , &xfs_bmbt_buf_ops))return (1 );/*
repair/scan.c +7 -4
@@ -139,7 +139,8 @@ scan_lbtree(int isroot, int check_dups, int *dirty, - uint64_t magic), + uint64_t magic, + void *priv), int type, int whichfork, xfs_ino_t ino,
@@ -150,6 +151,7 @@ scan_lbtree(int isroot, int check_dups, uint64_t magic, + void *priv, const struct xfs_buf_ops *ops) { struct xfs_buf *bp;
@@ -181,7 +183,7 @@ scan_lbtree( err = (*func)(XFS_BUF_TO_BLOCK (bp), nlevels -1 , type, whichfork, root, ino, tot, nex, blkmapp, bm_cursor, isroot, check_dups, &dirty, - magic); + magic, priv);ASSERT (dirty ==0 || (dirty && !no_modify));
@@ -210,7 +212,8 @@ scan_bmapbt(int isroot, int check_dups, int *dirty, - uint64_t magic) + uint64_t magic, + void *priv) { int i;int err;
@@ -486,7 +489,7 @@ _("bad bmap btree ptr 0x%llx in ino %" PRIu64 "\n"), err =scan_lbtree (be64_to_cpu (pp[i]), level, scan_bmapbt, type, whichfork, ino, tot, nex, blkmapp, - bm_cursor,0 , check_dups, magic, + bm_cursor,0 , check_dups, magic, priv, &xfs_bmbt_buf_ops);if (err)return (1 );
repair/scan.h +5 -2
@@ -26,7 +26,8 @@ int scan_lbtree(int isroot, int check_dups, int *dirty, - uint64_t magic), + uint64_t magic, + void *priv), int type, int whichfork, xfs_ino_t ino,
@@ -37,6 +38,7 @@ int scan_lbtree(int isroot, int check_dups, uint64_t magic, + void *priv, const struct xfs_buf_ops *ops); int scan_bmapbt(
@@ -53,7 +55,8 @@ int scan_bmapbt(int isroot, int check_dups, int *dirty, - uint64_t magic); + uint64_t magic, + void *priv);void scan_ags(
PATCH 34/41 xfs_repair: mark space used by metadata files
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
Track space used by metadata files as a separate incore extent type. This ensures that we can warn about cross-linked metadata files, even though we are going to rebuild the entire metadata directory tree in the end.
--- repair/dino_chunks.c | 31 +++++++++++++ repair/dinode.c | 122 ++++++++++++++++++++++++++++++++++++++------------ repair/dinode.h | 6 ++ repair/incore.h | 31 ++++++++----- repair/phase4.c | 2 + repair/scan.c | 30 +++++++++++- 6 files changed, 175 insertions(+), 47 deletions(-)
repair/dino_chunks.c +31 -0
@@ -141,6 +141,16 @@ verify_inode_chunk(xfs_mount_t *mp,_ ("uncertain inode block %d/%d already known\n" ), agno, agbno);break ; +case XR_E_METADATA : +/* +* Files in the metadata directory tree are always +* reconstructed, so it's ok to let go if this block +* is also a valid inode cluster. +*/ +do_warn ( +_ ("inode block %d/%d claimed by metadata file\n" ), + agno, agbno); + fallthrough;case XR_E_UNKNOWN :case XR_E_FREE1 :case XR_E_FREE :
@@ -430,6 +440,7 @@ verify_inode_chunk(xfs_mount_t *mp,set_bmap_ext (agno, cur_agbno, blen,XR_E_MULT );pthread_mutex_unlock (&ag_locks[agno].lock);return 0 ; +case XR_E_METADATA :case XR_E_INO : do_error( _("uncertain inode block overlap, agbno = %d, ino = %" PRIu64 "\n"),
@@ -474,6 +485,16 @@ verify_inode_chunk(xfs_mount_t *mp,_ ("uncertain inode block %" PRIu64" already known\n" ), XFS_AGB_TO_FSB(mp, agno, cur_agbno));break ; +case XR_E_METADATA : +/* +* Files in the metadata directory tree are always +* reconstructed, so it's ok to let go if this block +* is also a valid inode cluster. +*/ +do_warn ( +_ ("inode block %d/%d claimed by metadata file\n" ), + agno, agbno); + fallthrough;case XR_E_UNKNOWN :case XR_E_FREE1 :case XR_E_FREE :
@@ -559,6 +580,16 @@ process_inode_agbno_state(switch (state) {case XR_E_INO :/* already marked */ break ; +case XR_E_METADATA : +/* +* Files in the metadata directory tree are always +* reconstructed, so it's ok to let go if this block is also a +* valid inode cluster. +*/ +do_warn ( +_ ("inode block %d/%d claimed by metadata file\n" ), + agno, agbno); + fallthrough;case XR_E_UNKNOWN :case XR_E_FREE :case XR_E_FREE1 :
repair/dinode.c +93 -29
302 lines not on this page · raw message
repair/dinode.h +4 -2
@@ -27,7 +27,8 @@ process_bmbt_reclist(xfs_mount_t *mp,struct blkmap **blkmapp, uint64_t *first_key, uint64_t *last_key, - int whichfork); + int whichfork, + bool zap_metadata);int scan_bmbt_reclist(
@@ -37,7 +38,8 @@ scan_bmbt_reclist(int type, xfs_ino_t ino, xfs_rfsblock_t *tot, - int whichfork); + int whichfork, + bool zap_metadata);void update_rootino (xfs_mount_t *mp);
repair/incore.h +19 -12
@@ -85,18 +85,25 @@ typedef struct rt_extent_tree_node {#define XR_E_UNKNOWN 0/* unknown state */ #define XR_E_FREE1 1/* free block (marked by one fs space tree) */ #define XR_E_FREE 2/* free block (marked by both fs space trees) */ -#define XR_E_INUSE 3/* extent used by file/dir data or metadata */ -#define XR_E_INUSE_FS 4/* extent used by fs ag header or log */ -#define XR_E_MULT 5/* extent is multiply referenced */ -#define XR_E_INO 6/* extent used by inodes (inode blocks) */ -#define XR_E_FS_MAP 7/* extent used by fs space/inode maps */ -#define XR_E_INUSE1 8/* used block (marked by rmap btree) */ -#define XR_E_INUSE_FS1 9/* used by fs ag header or log (rmap btree) */ -#define XR_E_INO1 10/* used by inodes (marked by rmap btree) */ -#define XR_E_FS_MAP1 11/* used by fs space/inode maps (rmap btree) */ -#define XR_E_REFC 12/* used by fs ag reference count btree */ -#define XR_E_COW 13/* leftover cow extent */ -#define XR_E_BAD_STATE 14 +/* +* Space used by metadata files. The entire metadata directory tree will be +* rebuilt from scratch during phase 6, so this value must be less than +* XR_E_INUSE so that the space will go back to the free space btrees during +* phase 5. +*/ +#define XR_E_METADATA 3 +#define XR_E_INUSE 4/* extent used by file/dir data or metadata */ +#define XR_E_INUSE_FS 5/* extent used by fs ag header or log */ +#define XR_E_MULT 6/* extent is multiply referenced */ +#define XR_E_INO 7/* extent used by inodes (inode blocks) */ +#define XR_E_FS_MAP 8/* extent used by fs space/inode maps */ +#define XR_E_INUSE1 9/* used block (marked by rmap btree) */ +#define XR_E_INUSE_FS1 10/* used by fs ag header or log (rmap btree) */ +#define XR_E_INO1 11/* used by inodes (marked by rmap btree) */ +#define XR_E_FS_MAP1 12/* used by fs space/inode maps (rmap btree) */ +#define XR_E_REFC 13/* used by fs ag reference count btree */ +#define XR_E_COW 14/* leftover cow extent */ +#define XR_E_BAD_STATE 15/* separate state bit, OR'ed into high (4th) bit of ex_state field */
repair/phase4.c +2 -0
@@ -303,6 +303,7 @@ phase4(xfs_mount_t *mp)_ ("unknown block state, ag %d, blocks %u-%u\n" ), i, j, j + blen - 1); fallthrough; +case XR_E_METADATA :case XR_E_UNKNOWN :case XR_E_FREE :case XR_E_INUSE :
@@ -335,6 +336,7 @@ phase4(xfs_mount_t *mp)_ ("unknown rt extent state, extent %" PRIu64"\n" ), rtx); fallthrough; +case XR_E_METADATA :case XR_E_UNKNOWN :case XR_E_FREE1 :case XR_E_FREE :
repair/scan.c +26 -4
@@ -227,6 +227,7 @@ scan_bmapbt(xfs_agnumber_t agno;xfs_agblock_t agbno;int state; +bool zap_metadata = priv !=NULL ;/* * unlike the ag freeblock btrees, if anything looks wrong
@@ -352,7 +353,20 @@ _("bad back (left) sibling pointer (saw %llu should be NULL (0))\n"case XR_E_UNKNOWN :case XR_E_FREE1 :case XR_E_FREE : -set_bmap (agno, agbno,XR_E_INUSE ); +set_bmap (agno, agbno, zap_metadata ?XR_E_METADATA : +XR_E_INUSE ); +break ; +case XR_E_METADATA : +/* +* bmbt block already claimed by a metadata file. We +* always reconstruct the entire metadata tree, so if +* this is a regular file we mark it owned by the file. +*/ +do_warn ( +_ ("inode 0x%" PRIx64"bmap block 0x%" PRIx64" claimed by metadata file\n" ), + ino, bno); +if (!zap_metadata) +set_bmap (agno, agbno,XR_E_INUSE );break ;case XR_E_FS_MAP :case XR_E_INUSE :
@@ -364,7 +378,8 @@ _("bad back (left) sibling pointer (saw %llu should be NULL (0))\n"* we made it here, the block probably * contains btree data. */ -set_bmap (agno, agbno,XR_E_MULT ); +if (!zap_metadata) +set_bmap (agno, agbno,XR_E_MULT );do_warn (_ ("inode 0x%" PRIx64"bmap block 0x%" PRIx64" claimed, state is %d\n" ), ino, bno, state);
@@ -429,7 +444,8 @@ _("inode %" PRIu64 " bad # of bmap records (%" PRIu64 ", min - %u, max - %u)\n")if (check_dups ==0 ) { err =process_bmbt_reclist (mp, rp, &numrecs, type, ino, tot, blkmapp, &first_key, - &last_key, whichfork); + &last_key, whichfork, + zap_metadata);if (err)return 1 ;
@@ -459,7 +475,7 @@ _("out-of-order bmap key (file offset) in inode %" PRIu64 ", %s fork, fsbno %" Preturn 0 ; } else {return scan_bmbt_reclist (mp, rp, &numrecs, type, ino, - tot, whichfork); + tot, whichfork, zap_metadata); } } if (numrecs > mp->m_bmap_dmxr[1] || (isroot == 0 && numrecs <
@@ -849,6 +865,12 @@ process_rmap_rec(break ; }break ; +case XR_E_METADATA : +do_warn ( +_ ("Metadata file block (%d,%d-%d) mismatch in %s tree, state - %d,%" PRIx64"\n" ), + agno, b, b + blen -1 , + name, state, owner); +break ;case XR_E_INUSE_FS :if (owner ==XFS_RMAP_OWN_FS || owner ==XFS_RMAP_OWN_LOG )
PATCH 35/41 xfs_repair: adjust keep_fsinos to handle metadata directories
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
In keep_fsinos, mark the root of the metadata directory tree as inuse. The realtime bitmap and summary files still come after the root directories, so this is a fairly simple change to the loop test.
--- repair/phase5.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-)
repair/phase5.c +7 -2
@@ -419,13 +419,18 @@ static void keep_fsinos(xfs_mount_t *mp) {ino_tree_node_t *irec; -int i; +unsigned int inuse =xfs_rootrec_inodes_inuse (mp), i; irec =find_inode_rec (mp,XFS_INO_TO_AGNO (mp, mp->m_sb.sb_rootino),XFS_INO_TO_AGINO (mp, mp->m_sb.sb_rootino)); -for (i =0 ; i <3 ; i++) +for (i =0 ; i < inuse; i++) {set_inode_used (irec, i); + +/* Everything after the root dir is metadata */ +if (i) +set_inode_is_meta (irec, i); + } } static void
PATCH 36/41 xfs_repair: metadata dirs are never plausible root dirs
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
Metadata directories are never candidates to be the root of the user-accessible directory tree. Update has_plausible_rootdir to ignore them all, as well as detecting the case where the superblock incorrectly thinks both trees have the same root.
--- repair/xfs_repair.c | 6 ++++++ 1 file changed, 6 insertions(+)
repair/xfs_repair.c +6 -0
@@ -546,9 +546,15 @@ has_plausible_rootdir(int error;bool ret = false; +if (xfs_has_metadir (mp) && + mp->m_sb.sb_rootino == mp->m_sb.sb_metadirino) + goto out; + error = -libxfs_iget (mp,NULL , mp->m_sb.sb_rootino,0 , &ip);if (error) goto out; +if (xfs_is_metadir_inode (ip)) + goto out_rele;if (!S_ISDIR (VFS_I (ip)->i_mode)) goto out_rele;
PATCH 37/41 xfs_repair: drop all the metadata directory files during pass 4
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
Drop the entire metadata directory tree during pass 4 so that we can reinitialize the entire tree in phase 6. The existing metadata files (rtbitmap, rtsummary, quotas) will be reattached to the newly rebuilt directory tree.
--- repair/dinode.c | 14 +++++++++++++- repair/scan.c | 2 +- 2 files changed, 14 insertions(+), 2 deletions(-)
repair/dinode.c +13 -1
@@ -656,7 +656,7 @@ _("illegal state %d in block map %" PRIu64 "\n"),break ; } } -if (collect_rmaps)/* && !check_dups */ +if (collect_rmaps && !zap_metadata)/* && !check_dups */ rmap_add_rec (mp, ino, whichfork, &irec); *tot += irec.br_blockcount; }
@@ -3123,6 +3123,18 @@ _("Bad CoW extent size %u on inode %" PRIu64 ", "),*/ *dirty +=process_check_inode_nlink_version (dino, lino); +/* +* The entire metadata directory tree will be rebuilt during phase 6. +* Therefore, if we're at the end of phase 4 and this is a metadata +* file, zero the ondisk inode and the incore state. +*/ +if (check_dups && zap_metadata && !no_modify) { +clear_dinode (mp, dino, lino); + *dirty +=1 ; + *used = is_free; + *isa_dir =0 ; + } +return retval; clear_bad_out:
repair/scan.c +1 -1
@@ -418,7 +418,7 @@ _("bad state %d, inode %" PRIu64 " bmap block 0x%" PRIx64 "\n"), numrecs =be16_to_cpu (block->bb_numrecs);/* Record BMBT blocks in the reverse-mapping data. */ -if (check_dups && collect_rmaps) { +if (check_dups && collect_rmaps && !zap_metadata) { agno =XFS_FSB_TO_AGNO (mp, bno);pthread_mutex_lock (&ag_locks[agno].lock);rmap_add_bmbt_rec (mp, ino, whichfork, bno);
PATCH 38/41 xfs_repair: truncate and unmark orphaned metadata inodes
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
If an inode claims to be a metadata inode but wasn't linked in either directory tree, remove the attr fork and reset the data fork if the contents weren't regular extent mappings before moving the inode to the lost+found.
We don't ifree the inode, because it's possible that the inode was not actually a metadata inode but simply got corrupted due to bitflips or something, and we'd rather let the sysadmin examine what's left of the file instead of photorec'ing it.
--- repair/phase6.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+)
repair/phase6.c +50 -0
@@ -853,6 +853,53 @@ mk_orphanage(return (ino); } +/* Don't let metadata inode contents leak to lost+found. */ +static void +trunc_metadata_inode ( +struct xfs_inode *ip) +{ +struct xfs_trans *tp; +struct xfs_mount *mp = ip->i_mount; +int err; + + err = -libxfs_trans_alloc (mp, &M_RES (mp)->tr_ichange,0 ,0 ,0 , &tp); +if (err) +do_error ( +_ ("space reservation failed (%d), filesystem may be out of space\n" ), + err); + +libxfs_trans_ijoin (tp, ip,0 ); + ip->i_diflags2 &= ~XFS_DIFLAG2_METADATA ; + +switch (VFS_I (ip)->i_mode &S_IFMT ) { +case S_IFIFO : +case S_IFCHR : +case S_IFBLK : +case S_IFSOCK : + ip->i_df.if_format =XFS_DINODE_FMT_DEV ; +break ; +case S_IFREG : +switch (ip->i_df.if_format) { +case XFS_DINODE_FMT_EXTENTS : +case XFS_DINODE_FMT_BTREE : +break ; +default : + ip->i_df.if_format =XFS_DINODE_FMT_EXTENTS ; + ip->i_df.if_nextents =0 ; +break ; + } +break ; + } + +libxfs_trans_log_inode (tp, ip,XFS_ILOG_CORE ); + + err = -libxfs_trans_commit (tp); +if (err) +do_error ( +_ ("truncation of metadata inode 0x%llx failed, err=%d\n" ), + (unsigned long long )ip->i_ino, err); +} +/* * Add a parent pointer back to the orphanage for any file we're moving into * the orphanage, being careful not to trip over any existing parent pointer.
@@ -943,6 +990,9 @@ mv_orphanage(if (err)do_error (_ ("%d - couldn't iget disconnected inode\n" ), err); +if (xfs_is_metadir_inode (ino_p)) +trunc_metadata_inode (ino_p); + xname.type =libxfs_mode_to_ftype (VFS_I (ino_p)->i_mode);if (isa_dir) {
PATCH 39/41 xfs_repair: do not count metadata directory files when doing 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 offline quotacheck code in xfs_repair and xfs_check to reflect this.
--- repair/quotacheck.c | 5 +++++ 1 file changed, 5 insertions(+)
repair/quotacheck.c +5 -0
@@ -217,6 +217,10 @@ quotacheck_adjust(return ; } +/* Metadata directory files aren't counted in quota. */ +if (xfs_is_metadir_inode (ip)) + goto out_rele; +/* Count the file's blocks. */ if (XFS_IS_REALTIME_INODE (ip)) rtblks =qc_count_rtblocks (ip);
@@ -229,6 +233,7 @@ quotacheck_adjust(if (proj_dquots)qc_adjust (proj_dquots, ip->i_projid, blocks, rtblks); +out_rele:libxfs_irele (ip); }
PATCH 40/41 xfs_repair: refactor generate_rtinfo
In reply to Darrick J. WongFrom: Christoph Hellwig <[email protected]>
Move the allocation of the computed values into generate_rtinfo, and thus make the variables holding them private in rt.c, and clean up a few formatting nits.
--- repair/globals.c | 5 -- repair/globals.h | 5 -- repair/phase5.c | 3 - repair/phase6.c | 51 +---------------- repair/rt.c | 160 ++++++++++++++++++++++++++++++++---------------------- repair/rt.h | 12 +--- 6 files changed, 104 insertions(+), 132 deletions(-)
repair/globals.c +0 -5
@@ -87,11 +87,6 @@ unsigned int glob_agcount;int chunks_pblock;/* # of 64-ino chunks per allocation */ int max_symlink_blocks; -/* realtime info */ - -union xfs_rtword_raw *btmcompute; -union xfs_suminfo_raw *sumcompute; -/* inode tree records have full or partial backptr fields ? */ int full_ino_ex_data;/*
repair/globals.h +0 -5
@@ -128,11 +128,6 @@ extern unsigned int glob_agcount;extern int chunks_pblock;/* # of 64-ino chunks per allocation */ extern int max_symlink_blocks; -/* realtime info */ - -extern union xfs_rtword_raw *btmcompute; -extern union xfs_suminfo_raw *sumcompute; -/* inode tree records have full or partial backptr fields ? */ extern int full_ino_ex_data;/*
repair/phase5.c +1 -2
@@ -627,8 +627,7 @@ voidcheck_rtmetadata ( struct xfs_mount *mp) { -rtinit (mp); -generate_rtinfo (mp, btmcompute, sumcompute); +generate_rtinfo (mp);check_rtbitmap (mp);check_rtsummary (mp); }
repair/phase6.c +3 -48
69 lines not on this page · raw message
repair/rt.c +96 -64
206 lines not on this page · raw message
repair/rt.h +4 -8
@@ -6,15 +6,11 @@#ifndef _XFS_REPAIR_RT_H_#define _XFS_REPAIR_RT_H_ -struct blkmap ; - -void -rtinit (xfs_mount_t *mp); - -int generate_rtinfo (struct xfs_mount *mp,union xfs_rtword_raw *words, -union xfs_suminfo_raw *sumcompute); - +void generate_rtinfo (struct xfs_mount *mp);void check_rtbitmap (struct xfs_mount *mp);void check_rtsummary (struct xfs_mount *mp); +void fill_rtbitmap (struct xfs_mount *mp); +void fill_rtsummary (struct xfs_mount *mp); +#endif /* _XFS_REPAIR_RT_H_ */
PATCH 41/41 mkfs.xfs: enable metadata directories
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
Enable formatting filesystems with metadata directories.
--- libxfs/libxfs_api_defs.h | 2 + man/man8/mkfs.xfs.8.in | 11 +++++++ mkfs/lts_4.19.conf | 1 + mkfs/lts_5.10.conf | 1 + mkfs/lts_5.15.conf | 1 + mkfs/lts_5.4.conf | 1 + mkfs/lts_6.1.conf | 1 + mkfs/lts_6.12.conf | 1 + mkfs/lts_6.6.conf | 1 + mkfs/proto.c | 68 +++++++++++++++++++++++++++++++++++++++++++++- mkfs/xfs_mkfs.c | 33 +++++++++++++++++++++- 11 files changed, 118 insertions(+), 3 deletions(-)
libxfs/libxfs_api_defs.h +2 -0
@@ -215,6 +215,8 @@#define xfs_metafile_iget libxfs_metafile_iget#define xfs_trans_metafile_iget libxfs_trans_metafile_iget#define xfs_metafile_set_iflag libxfs_metafile_set_iflag +#define xfs_metadir_cancel libxfs_metadir_cancel +#define xfs_metadir_commit libxfs_metadir_commit#define xfs_metadir_link libxfs_metadir_link#define xfs_metadir_lookup libxfs_metadir_lookup#define xfs_metadir_start_create libxfs_metadir_start_create
man/man8/mkfs.xfs.8.in +11 -0
@@ -271,6 +271,17 @@ .SH OPTIONS When the option .B \-m finobt=0 is used, the inode btree counter feature is not supported and is disabled. +.TP +.BI metadir= value +This option creates an internal directory tree to store filesystem metadata. +.IP +By default, +.B mkfs.xfs +will not enable this feature. +If the option +.B \-m crc=0 +is used, the metadata directory feature is not supported and is disabled. + .TP .BI uuid= value Use the given value as the filesystem UUID for the newly created filesystem.
mkfs/lts_4.19.conf +1 -0
@@ -6,6 +6,7 @@ crc=1 finobt=1 inobtcount=0 +metadir=0 reflink=0 rmapbt=0 autofsck=0
mkfs/lts_5.10.conf +1 -0
@@ -6,6 +6,7 @@ crc=1 finobt=1 inobtcount=0 +metadir=0 reflink=1 rmapbt=0 autofsck=0
mkfs/lts_5.15.conf +1 -0
@@ -6,6 +6,7 @@ crc=1 finobt=1 inobtcount=1 +metadir=0 reflink=1 rmapbt=0 autofsck=0
mkfs/lts_5.4.conf +1 -0
@@ -6,6 +6,7 @@ crc=1 finobt=1 inobtcount=0 +metadir=0 reflink=1 rmapbt=0 autofsck=0
mkfs/lts_6.1.conf +1 -0
@@ -6,6 +6,7 @@ crc=1 finobt=1 inobtcount=1 +metadir=0 reflink=1 rmapbt=0 autofsck=0
mkfs/lts_6.12.conf +1 -0
@@ -6,6 +6,7 @@ crc=1 finobt=1 inobtcount=1 +metadir=0 reflink=1 rmapbt=1 autofsck=0
mkfs/lts_6.6.conf +1 -0
@@ -6,6 +6,7 @@ crc=1 finobt=1 inobtcount=1 +metadir=0 reflink=1 rmapbt=1 autofsck=0
mkfs/proto.c +67 -1
81 lines not on this page · raw message
mkfs/xfs_mkfs.c +31 -2
@@ -150,6 +150,7 @@ enum {M_INOBTCNT ,M_BIGTIME ,M_AUTOFSCK , +M_METADIR , M_MAX_OPTS, };
@@ -812,6 +813,7 @@ static struct opt_params mopts = { [M_INOBTCNT] = "inobtcount", [M_BIGTIME] = "bigtime", [M_AUTOFSCK] = "autofsck", + [M_METADIR] = "metadir", [M_MAX_OPTS ] =NULL , }, .subopt_params = {
@@ -861,6 +863,12 @@ static struct opt_params mopts = { .maxval = 1, .defaultval = 1, }, + { .index = M_METADIR, + .conflicts = { { NULL, LAST_CONFLICT } }, + .minval = 0, + .maxval = 1, + .defaultval = 1, + }, }, };
@@ -913,6 +921,7 @@ struct sb_feat_args {bool reflink;/* XFS_SB_FEAT_RO_COMPAT_REFLINK */ bool inobtcnt;/* XFS_SB_FEAT_RO_COMPAT_INOBTCNT */ bool bigtime;/* XFS_SB_FEAT_INCOMPAT_BIGTIME */ +bool metadir;/* XFS_SB_FEAT_INCOMPAT_METADIR */ bool nodalign;bool nortalign;bool nrext64;
@@ -1048,7 +1057,8 @@ usage( void ) /* blocksize */ [-b size=num]\n\ /* config file */ [-c options=xxx]\n\ /* metadata */ [-m crc=0|1,finobt=0|1,uuid=xxx,rmapbt=0|1,reflink=0|1,\n\ - inobtcount=0|1,bigtime=0|1,autofsck=xxx]\n\ + inobtcount=0|1,bigtime=0|1,autofsck=xxx,\n\ + metadir=0|1]\n\ /* data subvol */ [-d agcount=n,agsize=n,file,name=xxx,size=num,\n\ (sunit=value,swidth=value|su=num,sw=num|noalign),\n\ sectsize=num,concurrency=num]\n\
@@ -1883,6 +1893,9 @@ meta_opts_parser(illegal (value,"m autofsck" ); }break ; +case M_METADIR : + cli->sb_feat.metadir =getnum (value, opts, subopt); +break ;default :return -EINVAL ; }
@@ -2465,6 +2478,14 @@ _("autofsck not supported without CRC support\n"));usage (); } cli->autofsck =FSPROP_AUTOFSCK_UNSET ; + +if (cli->sb_feat.metadir && +cli_opt_set (&mopts,M_METADIR )) { +fprintf (stderr, +_ ("metadata directory not supported without CRC support\n" )); +usage (); + } + cli->sb_feat.metadir = false; }if (!cli->sb_feat.finobt) {
@@ -3568,7 +3589,8 @@ sb_set_features(* the sb_bad_features2 field. To avoid older kernels mounting * filesystems they shouldn't, set both field to the same value. */ - sbp->sb_bad_features2 = sbp->sb_features2; +if (!fp->metadir) + sbp->sb_bad_features2 = sbp->sb_features2;if (!fp->crcs_enabled)return ;
@@ -3618,6 +3640,8 @@ sb_set_features(*/ sbp->sb_versionnum |=XFS_SB_VERSION_ATTRBIT ; } +if (fp->metadir) + sbp->sb_features_incompat |=XFS_SB_FEAT_INCOMPAT_METADIR ; }/*
@@ -4053,6 +4077,7 @@ finish_superblock_setup(platform_uuid_copy (&sbp->sb_meta_uuid, &cfg->uuid); sbp->sb_logstart = cfg->logstart; sbp->sb_rootino = sbp->sb_rbmino = sbp->sb_rsumino =NULLFSINO ; + sbp->sb_metadirino =NULLFSINO ; sbp->sb_agcount = (xfs_agnumber_t )cfg->agcount; sbp->sb_rbmblocks = cfg->rtbmblocks; sbp->sb_logblocks = (xfs_extlen_t )cfg->logblocks;
@@ -4279,6 +4304,8 @@ rewrite_secondary_superblocks( } dsb = buf->b_addr; dsb->sb_rootino =cpu_to_be64 (mp->m_sb.sb_rootino); +if (xfs_has_metadir (mp)) + dsb->sb_metadirino =cpu_to_be64 (mp->m_sb.sb_metadirino);libxfs_buf_mark_dirty (buf);libxfs_buf_relse (buf);
@@ -4297,6 +4324,8 @@ rewrite_secondary_superblocks( } dsb = buf->b_addr; dsb->sb_rootino =cpu_to_be64 (mp->m_sb.sb_rootino); +if (xfs_has_metadir (mp)) + dsb->sb_metadirino =cpu_to_be64 (mp->m_sb.sb_metadirino);libxfs_buf_mark_dirty (buf);libxfs_buf_relse (buf); }
PATCH 4/8 mkfs: make protofiles less janky
In reply to Darrick J. WongHi all,
Here are some minor improvements to the protofile code in mkfs. First, we improve the file copy-in code to avoid allocating gigantic heap buffers by replacing it with a SEEK_{DATA,HOLE} loop and only copying a fixed size buffer. Next, we add the ability to pull in extended attributes. Finally, we add a program to generate a protofile from a directory tree.
Originally this code refactoring was intended to support more efficient construction of rt bitmap and summary files, but that was subsequently refactored into libxfs. However, the cleanups still make the protofile code less disgusting, so they're being submitted anyway.
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
xfsprogs git tree:
https://git.kernel.org/cgit/linux/kernel/git/djwong/xfsprogs-dev.git/log/?h=protofiles
fstests git tree:
https://git.kernel.org/cgit/linux/kernel/git/djwong/xfstests-dev.git/log/?h=protofiles
---
Commits in this patchset:
* libxfs: resync libxfs_alloc_file_space interface with the kernel
* mkfs: support copying in large or sparse files
* mkfs: support copying in xattrs
* mkfs: add a utility to generate protofiles
--- include/libxfs.h | 6 + libxfs/util.c | 207 +++++++++++++++++++++++++++-------- man/man8/xfs_protofile.8 | 33 ++++++ mkfs/Makefile | 10 ++ mkfs/proto.c | 269 ++++++++++++++++++++++++++++++++++------------ mkfs/xfs_protofile.in | 152 ++++++++++++++++++++++++++ 6 files changed, 557 insertions(+), 120 deletions(-) create mode 100644 man/man8/xfs_protofile.8 create mode 100644 mkfs/xfs_protofile.in
PATCH 1/4 libxfs: resync libxfs_alloc_file_space interface with the kernel
From: Darrick J. Wong <[email protected]>
Make the userspace xfs_alloc_file_space behave (more or less) like the kernel version, at least as far as the interface goes.
--- include/libxfs.h | 4 +- libxfs/util.c | 140 ++++++++++++++++++++++++++++++++++++------------------ mkfs/proto.c | 2 - 3 files changed, 96 insertions(+), 50 deletions(-)
include/libxfs.h +2 -2
@@ -176,8 +176,8 @@ extern int libxfs_log_header(char *, uuid_t *, int, int, int, xfs_lsn_t,/* Shared utility routines */ -extern int libxfs_alloc_file_space (struct xfs_inode *,xfs_off_t , -xfs_off_t ,int ,int ); +int libxfs_alloc_file_space (struct xfs_inode *ip,xfs_off_t offset, +xfs_off_t len,uint32_t bmapi_flags);/* XXX: this is messy and needs fixing */ #ifndef __LIBXFS_INTERNAL_XFS_H__
libxfs/util.c +93 -47
171 lines not on this page · raw message
mkfs/proto.c +1 -1
@@ -203,7 +203,7 @@ rsvfile(int error;xfs_trans_t *tp; - error = -libxfs_alloc_file_space (ip,0 , llen,1 ,0 ); + error = -libxfs_alloc_file_space (ip,0 , llen,XFS_BMAPI_PREALLOC );if (error) {fail (_ ("error reserving space for a file" ), error);
PATCH 2/4 mkfs: support copying in large or sparse files
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
Restructure the protofile code to handle sparse files and files that are larger than the program's address space.
--- include/libxfs.h | 2 + libxfs/util.c | 67 +++++++++++++++++++++ mkfs/proto.c | 175 ++++++++++++++++++++++++++++++++---------------------- 3 files changed, 174 insertions(+), 70 deletions(-)
include/libxfs.h +2 -0
@@ -178,6 +178,8 @@ extern int libxfs_log_header(char *, uuid_t *, int, int, int, xfs_lsn_t,int libxfs_alloc_file_space (struct xfs_inode *ip,xfs_off_t offset,xfs_off_t len,uint32_t bmapi_flags); +int libxfs_file_write (struct xfs_inode *ip,void *buf,off_t pos, +size_t len);/* XXX: this is messy and needs fixing */ #ifndef __LIBXFS_INTERNAL_XFS_H__
libxfs/util.c +67 -0
70 lines not on this page · raw message
mkfs/proto.c +105 -70
247 lines not on this page · raw message
PATCH 3/4 mkfs: support copying in xattrs
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
Update the protofile code to import extended attributes from the source files.
--- mkfs/proto.c | 94 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+)
mkfs/proto.c +94 -0
@@ -6,6 +6,8 @@#include "libxfs.h" #include <sys/stat.h> +#include <sys/xattr.h> +#include <linux/xattr.h> #include "libfrog/convert.h" #include "proto.h"
@@ -359,6 +361,97 @@ writefile(fail (_ ("error committing isize transaction" ), error); } +static void +writeattr ( +struct xfs_inode *ip, +const char *fname, +int fd, +const char *attrname, +char *valuebuf, +size_t valuelen) +{ +struct xfs_da_args args = { + .dp = ip, + .geo = ip->i_mount->m_attr_geo, + .owner = ip->i_ino, + .whichfork =XFS_ATTR_FORK , + .op_flags =XFS_DA_OP_OKNOENT , + .value = valuebuf, + }; +ssize_t ret; +int error; + + ret =fgetxattr (fd, attrname, valuebuf, valuelen); +if (ret <0 ) { +if (errno ==EOPNOTSUPP ) +return ; +fail (_ ("error collecting xattr value" ), errno); + } +if (ret ==0 ) +return ; + +if (!strncmp (attrname,XATTR_TRUSTED_PREFIX ,XATTR_TRUSTED_PREFIX_LEN )) { + args.name = (unsigned char *)attrname +XATTR_TRUSTED_PREFIX_LEN ; + args.attr_filter =LIBXFS_ATTR_ROOT ; + }else if (!strncmp (attrname,XATTR_SECURITY_PREFIX ,XATTR_SECURITY_PREFIX_LEN )) { + args.name = (unsigned char *)attrname +XATTR_SECURITY_PREFIX_LEN ; + args.attr_filter =LIBXFS_ATTR_SECURE ; + }else if (!strncmp (attrname,XATTR_USER_PREFIX ,XATTR_USER_PREFIX_LEN )) { + args.name = (unsigned char *)attrname +XATTR_USER_PREFIX_LEN ; + args.attr_filter =0 ; + }else { + args.name = (unsigned char *)attrname; + args.attr_filter =0 ; + } + args.namelen =strlen ((char *)args.name); + + args.valuelen = ret; +libxfs_attr_sethash (&args); + + error = -libxfs_attr_set (&args,XFS_ATTRUPDATE_UPSERT , false); +if (error) +fail (_ ("setting xattr value" ), error); +} + +static void +writeattrs ( +struct xfs_inode *ip, +const char *fname, +int fd) +{ +char *namebuf, *p, *end; +char *valuebuf =NULL ; +ssize_t ret; + + namebuf =malloc (XATTR_LIST_MAX ); +if (!namebuf) +fail (_ ("error allocating xattr name buffer" ), errno); + + ret =flistxattr (fd, namebuf,XATTR_LIST_MAX ); +if (ret <0 ) { +if (errno ==EOPNOTSUPP ) + goto out_namebuf; +fail (_ ("error collecting xattr names" ), errno); + } + + p = namebuf; + end = namebuf + ret; +for (p = namebuf; p < end; p +=strlen (p) +1 ) { +if (!valuebuf) { + valuebuf =malloc (ATTR_MAX_VALUELEN ); +if (!valuebuf) +fail (_ ("error allocating xattr value buffer" ), + errno); + } + +writeattr (ip, fname, fd, p, valuebuf,ATTR_MAX_VALUELEN ); + } + +free (valuebuf); +out_namebuf: +free (namebuf); +} + static int newregfile( char **pp,
@@ -833,6 +926,7 @@ parseproto(libxfs_parent_finish (mp, ppargs);if (fmt ==IF_REGULAR ) {writefile (ip, fname, fd); +writeattrs (ip, fname, fd);close (fd); }libxfs_irele (ip);
PATCH 4/4 mkfs: add a utility to generate protofiles
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
Add a new utility to generate mkfs protofiles from a directory tree.
--- man/man8/xfs_protofile.8 | 33 ++++++++++ mkfs/Makefile | 10 +++ mkfs/xfs_protofile.in | 152 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 194 insertions(+), 1 deletion(-) create mode 100644 man/man8/xfs_protofile.8 create mode 100644 mkfs/xfs_protofile.in
man/man8/xfs_protofile.8 new file +33 -0
@@ -0,0 +1,33 @@ +.TH xfs_protofile 8 +.SH NAME +xfs_protofile \- create a protofile for use with mkfs.xfs +.SH SYNOPSIS +.B xfs_protofile +.I path +[ +.I paths... +] +.br +.B xfs_protofile \-V +.SH DESCRIPTION +.B xfs_protofile +walks a directory tree to generate a protofile. +The protofile format is specified in the +.BR mkfs.xfs (8) +manual page and is derived from 3rd edition Unix. +.SH OPTIONS +.TP 1.0i +.I path +Create protofile directives to copy this path into the root directory. +If the path is a directory, protofile directives will be emitted to +replicate the entire subtree as a subtree of the root directory. +If the path is a not a directory, protofile directives will be emitted +to create the file as an entry in the root directory. +The first path must resolve to a directory. + +.SH BUGS +Filenames cannot contain spaces. +Extended attributes are not copied into the filesystem. + +.PD +.RE
mkfs/Makefile +9 -1
@@ -6,6 +6,7 @@ TOPDIR = .. include $(TOPDIR)/include/builddefs LTCOMMAND = mkfs.xfs +XFS_PROTOFILE = xfs_protofile HFILES = CFILES = proto.c xfs_mkfs.c
@@ -23,14 +24,21 @@ LLDLIBS += $(LIBXFS) $(LIBXCMD) $(LIBFROG) $(LIBRT) $(LIBBLKID) \ $(LIBUUID) $(LIBINIH) $(LIBURCU) $(LIBPTHREAD) LTDEPENDENCIES += $(LIBXFS) $(LIBXCMD) $(LIBFROG) LLDFLAGS = -static-libtool-libs +DIRT = $(XFS_PROTOFILE) -default: depend $(LTCOMMAND) $(CFGFILES) +default: depend $(LTCOMMAND) $(CFGFILES) $(XFS_PROTOFILE) include $(BUILDRULES) +$(XFS_PROTOFILE): $(XFS_PROTOFILE).in + @echo " [SED] $@" + $(Q)$(SED) -e "s|@pkg_version@|$(PKG_VERSION)|g" < $< > $@ + $(Q)chmod a+x $@ + install: default $(INSTALL) -m 755 -d $(PKG_SBIN_DIR) $(LTINSTALL) -m 755 $(LTCOMMAND) $(PKG_SBIN_DIR) + $(INSTALL) -m 755 $(XFS_PROTOFILE) $(PKG_SBIN_DIR) $(INSTALL) -m 755 -d $(MKFS_CFG_DIR) $(INSTALL) -m 644 $(CFGFILES) $(MKFS_CFG_DIR)
mkfs/xfs_protofile.in new file +152 -0
152 lines not on this page · raw message
PATCH 5/8 xfsprogs: new code for 6.13
In reply to Darrick J. WongHi all,
New code for 6.12.
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=xfs-6.13-merge
xfsprogs git tree:
https://git.kernel.org/cgit/linux/kernel/git/djwong/xfsprogs-dev.git/log/?h=xfs-6.13-merge
---
Commits in this patchset:
* xfs: create incore realtime group structures
* xfs: define locking primitives for realtime groups
* xfs: add a lockdep class key for rtgroup inodes
* xfs: support caching rtgroup metadata inodes
* xfs: add a xfs_bmap_free_rtblocks helper
* xfs: move RT bitmap and summary information to the rtgroup
* xfs: support creating per-RTG files in growfs
* xfs: refactor xfs_rtbitmap_blockcount
* xfs: refactor xfs_rtsummary_blockcount
* xfs: make RT extent numbers relative to the rtgroup
* libfrog: add memchr_inv
* xfs: define the format of rt groups
* xfs: update realtime super every time we update the primary fs super
* xfs: export realtime group geometry via XFS_FSOP_GEOM
* xfs: check that rtblock extents do not break rtsupers or rtgroups
* xfs: add a helper to prevent bmap merges across rtgroup boundaries
* xfs: add frextents to the lazysbcounters when rtgroups enabled
* xfs: record rt group metadata errors in the health system
* xfs: export the geometry of realtime groups to userspace
* xfs: add block headers to realtime bitmap and summary blocks
* xfs: encode the rtbitmap in big endian format
* xfs: encode the rtsummary in big endian format
* xfs: grow the realtime section when realtime groups are enabled
* xfs: support logging EFIs for realtime extents
* xfs: support error injection when freeing rt extents
* xfs: use realtime EFI to free extents when rtgroups are enabled
* xfs: don't merge ioends across RTGs
* xfs: make the RT allocator rtgroup aware
* xfs: scrub the realtime group superblock
* xfs: scrub metadir paths for rtgroup metadata
* xfs: mask off the rtbitmap and summary inodes when metadir in use
* xfs: create helpers to deal with rounding xfs_fileoff_t to rtx boundaries
* xfs: create helpers to deal with rounding xfs_filblks_t to rtx boundaries
* xfs: make xfs_rtblock_t a segmented address like xfs_fsblock_t
* xfs: adjust min_block usage in xfs_verify_agbno
* xfs: move the min and max group block numbers to xfs_group
* xfs: implement busy extent tracking for rtgroups
* xfs: use metadir for quota inodes
* xfs: scrub quota file metapaths
* xfs: enable metadata directory feature
* xfs: convert struct typedefs in xfs_ondisk.h
* xfs: separate space btree structures in xfs_ondisk.h
* xfs: port ondisk structure checks from xfs/122 to the kernel
* xfs: remove unknown compat feature check in superblock write validation
* xfs: fix sparse inode limits on runt AG
* xfs: switch to multigrain timestamps
* xfs: don't call xfs_bmap_same_rtgroup in xfs_bmap_add_extent_hole_delay
* xfs: return a 64-bit block count from xfs_btree_count_blocks
* xfs: fix error bailout in xfs_rtginode_create
* xfs: update btree keys correctly when _insrec splits an inode root block
* xfs: fix sb_spino_align checks for large fsblock sizes
* xfs: return from xfs_symlink_verify early on V4 filesystems
--- db/block.c | 2 db/block.h | 16 - db/convert.c | 1 db/faddr.c | 1 include/libxfs.h | 2 include/platform_defs.h | 33 ++ include/xfs_mount.h | 30 +- include/xfs_trace.h | 7 include/xfs_trans.h | 1 libfrog/util.c | 14 + libfrog/util.h | 4 libxfs/Makefile | 2 libxfs/init.c | 35 ++ libxfs/libxfs_api_defs.h | 16 + libxfs/libxfs_io.h | 1 libxfs/libxfs_priv.h | 34 -- libxfs/rdwr.c | 17 + libxfs/trans.c | 29 ++ libxfs/util.c | 8 libxfs/xfs_ag.c | 22 + libxfs/xfs_ag.h | 16 - libxfs/xfs_alloc.c | 15 + libxfs/xfs_alloc.h | 12 + libxfs/xfs_bmap.c | 124 ++++++-- libxfs/xfs_btree.c | 33 ++ libxfs/xfs_btree.h | 2 libxfs/xfs_defer.c | 6 libxfs/xfs_defer.h | 1 libxfs/xfs_dquot_buf.c | 190 ++++++++++++ libxfs/xfs_format.h | 80 +++++ libxfs/xfs_fs.h | 32 ++ libxfs/xfs_group.h | 33 ++ libxfs/xfs_health.h | 42 ++- libxfs/xfs_ialloc.c | 16 + libxfs/xfs_ialloc_btree.c | 6 libxfs/xfs_log_format.h | 6 libxfs/xfs_ondisk.h | 186 +++++++++--- libxfs/xfs_quota_defs.h | 43 +++ libxfs/xfs_rtbitmap.c | 405 +++++++++++++++++-------- libxfs/xfs_rtbitmap.h | 247 ++++++++++----- libxfs/xfs_rtgroup.c | 694 +++++++++++++++++++++++++++++++++++++++++++ libxfs/xfs_rtgroup.h | 284 ++++++++++++++++++ libxfs/xfs_sb.c | 246 ++++++++++++++- libxfs/xfs_sb.h | 6 libxfs/xfs_shared.h | 4 libxfs/xfs_symlink_remote.c | 4 libxfs/xfs_trans_inode.c | 6 libxfs/xfs_trans_resv.c | 2 libxfs/xfs_types.c | 35 ++ libxfs/xfs_types.h | 8 mkfs/proto.c | 33 +- mkfs/xfs_mkfs.c | 8 repair/dinode.c | 4 repair/phase6.c | 203 ++++++------- repair/rt.c | 34 -- repair/rt.h | 4 56 files changed, 2728 insertions(+), 617 deletions(-) create mode 100644 libxfs/xfs_rtgroup.c create mode 100644 libxfs/xfs_rtgroup.h
PATCH 1/52 xfs: create incore realtime group structures
From: Darrick J. Wong <[email protected]>
Source kernel commit: 87fe4c34a383d51ec75f254240bcd08828f4ce5a
Create an incore object that will contain information about a realtime allocation group. This will eventually enable us to shard the realtime section in a similar manner to how we shard the data section, but for now just a single object for the entire RT subvolume is created.
--- db/block.h | 16 --- db/convert.c | 1 db/faddr.c | 1 include/libxfs.h | 1 include/platform_defs.h | 33 +++++++ include/xfs_mount.h | 16 +++ include/xfs_trace.h | 7 + libxfs/Makefile | 2 libxfs/init.c | 17 ++++ libxfs/libxfs_api_defs.h | 4 + libxfs/libxfs_priv.h | 33 ------- libxfs/xfs_format.h | 3 + libxfs/xfs_rtgroup.c | 149 ++++++++++++++++++++++++++++++++ libxfs/xfs_rtgroup.h | 217 ++++++++++++++++++++++++++++++++++++++++++++++ libxfs/xfs_sb.c | 13 +++ libxfs/xfs_types.h | 8 +- mkfs/xfs_mkfs.c | 8 ++ 17 files changed, 477 insertions(+), 52 deletions(-) create mode 100644 libxfs/xfs_rtgroup.c create mode 100644 libxfs/xfs_rtgroup.h
db/block.h +0 -16
@@ -11,20 +11,4 @@ struct field;extern void block_init (void );extern void print_block (const struct field *fields,int argc,char **argv); -static inline xfs_daddr_t -xfs_rtb_to_daddr ( -struct xfs_mount *mp, -xfs_rtblock_t rtb) -{ -return rtb << mp->m_blkbb_log; -} - -static inline xfs_rtblock_t -xfs_daddr_to_rtb ( -struct xfs_mount *mp, -xfs_daddr_t daddr) -{ -return daddr >> mp->m_blkbb_log; -} -#endif /* __XFS_DB_BLOCK_H */
db/convert.c +0 -1
@@ -8,7 +8,6 @@#include "command.h" #include "output.h" #include "init.h" -#include "block.h" #define M (A ) (1 << CT_ ## A)#define agblock_to_bytes (x) \
db/faddr.c +0 -1
@@ -15,7 +15,6 @@#include "bmap.h" #include "output.h" #include "init.h" -#include "block.h" void fa_agblock(
include/libxfs.h +1 -0
@@ -97,6 +97,7 @@ struct iomap;#include "xfs_ag_resv.h" #include "xfs_metafile.h" #include "xfs_metadir.h" +#include "xfs_rtgroup.h" #ifndef ARRAY_SIZE #define ARRAY_SIZE (x) (sizeof(x) / sizeof((x)[0]))
include/platform_defs.h +33 -0
@@ -228,4 +228,37 @@ static inline size_t __ab_c_size(size_t a, size_t b, size_t c)*/ #define IS_ENABLED (option) __or(IS_BUILTIN(option), IS_MODULE(option)) +/* miscellaneous kernel routines not in user space */ +#define likely (x) (x) +#define unlikely (x) (x) + +#define __must_check __attribute__((__warn_unused_result__)) + +/* +* Allows for effectively applying __must_check to a macro so we can have +* both the type-agnostic benefits of the macros while also being able to +* enforce that the return value is, in fact, checked. +*/ +static inline bool __must_check __must_check_overflow (bool overflow) +{ +return unlikely (overflow); +} + +/* +* For simplicity and code hygiene, the fallback code below insists on +* a, b and *d having the same type (similar to the min() and max() +* macros), whereas gcc's type-generic overflow checkers accept +* different types. Hence we don't just make check_add_overflow an +* alias for __builtin_add_overflow, but add type checks similar to +* below. +*/ +#define check_add_overflow (a, b, d) __must_check_overflow(({ \ + typeof(a) __a = (a); \ + typeof(b) __b = (b); \ + typeof(d) __d = (d); \ + (void) (&__a == &__b); \ + (void) (&__a == __d); \ + __builtin_add_overflow(__a, __b, __d); \ +})) +#endif /* __XFS_PLATFORM_DEFS_H__ */
include/xfs_mount.h +16 -0
@@ -82,6 +82,7 @@ typedef struct xfs_mount {struct xfs_ino_geometry m_ino_geo;/* inode geometry */ uint m_rsumlevels;/* rt summary levels */ xfs_filblks_t m_rsumblocks;/* size of rt summary, FSBs */ +uint32_t m_rgblocks;/* size of rtgroup in rtblocks */ /* * Optional cache of rt summary level per bitmap block with the * invariant that m_rsum_cache[bbno] <= the minimum i for which
@@ -104,6 +105,7 @@ typedef struct xfs_mount {uint8_t m_sectbb_log;/* sectorlog - BBSHIFT */ uint8_t m_agno_log;/* log #ag's */ int8_t m_rtxblklog;/* log2 of rextsize, if possible */ +int8_t m_rgblklog;/* log2 of rt group sz if possible */ uint m_blockmask;/* sb_blocksize-1 */ uint m_blockwsize;/* sb_blocksize in words */ uint m_blockwmask;/* blockwsize-1 */
@@ -127,6 +129,7 @@ typedef struct xfs_mount {uint64_t m_features;/* active filesystem features */ uint64_t m_low_space[XFS_LOWSP_MAX ];uint64_t m_rtxblkmask;/* rt extent block mask */ +uint64_t m_rgblkmask;/* rt group block mask */ unsigned long m_opstate;/* dynamic state flags */ bool m_finobt_nores;/* no per-AG finobt resv. */ uint m_qflags;/* quota status flags */
@@ -250,6 +253,17 @@ __XFS_HAS_FEAT(large_extent_counts, NREXT64) __XFS_HAS_FEAT(exchange_range, EXCHANGE_RANGE) __XFS_HAS_FEAT(metadir, METADIR) + +static inline bool xfs_has_rtgroups (struct xfs_mount *mp) +{ +return false; +} + +static inline bool xfs_has_rtsb (struct xfs_mount *mp) +{ +return false; +} +/* Kernel mount features that we don't support */ #define __XFS_UNSUPP_FEAT (name) \ static inline bool xfs_has_ ## name (struct xfs_mount *mp) \
@@ -269,6 +283,7 @@ __XFS_UNSUPP_FEAT(grpid)#define XFS_OPSTATE_DEBUGGER 1/* is this the debugger? */ #define XFS_OPSTATE_REPORT_CORRUPTION 2/* report buffer corruption? */ #define XFS_OPSTATE_PERAG_DATA_LOADED 3/* per-AG data initialized? */ +#define XFS_OPSTATE_RTGROUP_DATA_LOADED 4/* rtgroup data initialized? */ #define __XFS_IS_OPSTATE (name,NAME ) \ static inline bool xfs_is_ ## name (struct xfs_mount *mp) \
@@ -294,6 +309,7 @@ __XFS_IS_OPSTATE(inode32, INODE32) __XFS_IS_OPSTATE(debugger, DEBUGGER) __XFS_IS_OPSTATE(reporting_corruption, REPORT_CORRUPTION) __XFS_IS_OPSTATE(perag_data_loaded, PERAG_DATA_LOADED) +__XFS_IS_OPSTATE(rtgroup_data_loaded, RTGROUP_DATA_LOADED)#define __XFS_UNSUPP_OPSTATE (name) \ static inline bool xfs_is_ ## name (struct xfs_mount *mp) \
include/xfs_trace.h +7 -0
@@ -356,6 +356,13 @@#define trace_xfs_exchmaps_overhead (...) ((void) 0)#define trace_xfs_exchmaps_update_inode_size (...) ((void) 0) +/* set c = c to avoid unused var warnings */ +#define trace_xfs_rtgroup_get (a,b) ((a) = (a)) +#define trace_xfs_rtgroup_hold (a,b) ((a) = (a)) +#define trace_xfs_rtgroup_put (a,b) ((a) = (a)) +#define trace_xfs_rtgroup_grab (a,b) ((a) = (a)) +#define trace_xfs_rtgroup_rele (a,b) ((a) = (a)) +#define trace_xfs_fs_mark_healthy (a,b) ((void) 0)#define trace_xlog_intent_recovery_failed (...) ((void) 0)
libxfs/Makefile +2 -0
@@ -64,6 +64,7 @@ HFILES = \ xfs_rmap.h \ xfs_rmap_btree.h \ xfs_rtbitmap.h \ + xfs_rtgroup.h \ xfs_sb.h \ xfs_shared.h \ xfs_trans_resv.h \
@@ -124,6 +125,7 @@ CFILES = buf_mem.c \ xfs_rmap.c \ xfs_rmap_btree.c \ xfs_rtbitmap.c \ + xfs_rtgroup.c \ xfs_sb.c \ xfs_symlink_remote.c \ xfs_trans_inode.c \
libxfs/init.c +17 -0
@@ -32,6 +32,7 @@#include "xfs_ondisk.h" #include "libxfs.h" /* for now */ +#include "xfs_rtgroup.h" #ifndef HAVE_LIBURCU_ATOMIC64 pthread_mutex_t atomic64_lock =PTHREAD_MUTEX_INITIALIZER ;
@@ -670,6 +671,7 @@ libxfs_mount( {struct xfs_buf *bp;struct xfs_sb *sbp; +struct xfs_rtgroup *rtg =NULL ;xfs_daddr_t d;int i;int error;
@@ -824,6 +826,19 @@ libxfs_mount(if (xfs_has_metadir (mp))libxfs_mount_setup_metadir (mp); + error =libxfs_initialize_rtgroups (mp,0 , sbp->sb_rgcount, + sbp->sb_rextents); +if (error) { +fprintf (stderr,_ ("%s: rtgroup init failed\n" ), + progname); +exit (1 ); + } + +while ((rtg =xfs_rtgroup_next (mp, rtg))) + rtg->rtg_extents =xfs_rtgroup_extents (mp,rtg_rgno (rtg)); + +xfs_set_rtgroup_data_loaded (mp); +return mp; out_da:xfs_da_unmount (mp);
@@ -957,6 +972,8 @@ libxfs_umount(* Only try to free the per-AG structures if we set them up in the * first place. */ +if (xfs_is_rtgroup_data_loaded (mp)) +libxfs_free_rtgroups (mp,0 , mp->m_sb.sb_rgcount);if (xfs_is_perag_data_loaded (mp))libxfs_free_perag_range (mp,0 , mp->m_sb.sb_agcount);
libxfs/libxfs_api_defs.h +4 -0
@@ -168,6 +168,7 @@#define xfs_free_extent libxfs_free_extent#define xfs_free_extent_later libxfs_free_extent_later#define xfs_free_perag_range libxfs_free_perag_range +#define xfs_free_rtgroups libxfs_free_rtgroups#define xfs_fs_geometry libxfs_fs_geometry#define xfs_gbno_to_fsb libxfs_gbno_to_fsb#define xfs_get_initial_prid libxfs_get_initial_prid
@@ -189,6 +190,7 @@#define xfs_initialize_perag libxfs_initialize_perag#define xfs_initialize_perag_data libxfs_initialize_perag_data +#define xfs_initialize_rtgroups libxfs_initialize_rtgroups#define xfs_init_local_fork libxfs_init_local_fork#define xfs_inobt_init_cursor libxfs_inobt_init_cursor
@@ -276,6 +278,8 @@#define xfs_rtbitmap_setword libxfs_rtbitmap_setword#define xfs_rtbitmap_wordcount libxfs_rtbitmap_wordcount +#define xfs_rtgroup_alloc libxfs_rtgroup_alloc +#define xfs_suminfo_add libxfs_suminfo_add#define xfs_suminfo_get libxfs_suminfo_get#define xfs_rtsummary_wordcount libxfs_rtsummary_wordcount
libxfs/libxfs_priv.h +0 -33
@@ -204,10 +204,6 @@ enum ce { CE_DEBUG, CE_CONT, CE_NOTE, CE_WARN, CE_ALERT, CE_PANIC };#define xfs_info_once (dev, fmt, ...) \ xfs_printk_once(xfs_info, dev, fmt, ##__VA_ARGS__) -/* miscellaneous kernel routines not in user space */ -#define likely (x) (x) -#define unlikely (x) (x) -/* Need to be able to handle this bare or in control flow */ static inline bool WARN_ON (bool expr) {return (expr);
@@ -238,35 +234,6 @@ struct mnt_idmap;void inode_init_owner (struct mnt_idmap *idmap,struct inode *inode,const struct inode *dir,umode_t mode); -#define __must_check __attribute__((__warn_unused_result__)) - -/* -* Allows for effectively applying __must_check to a macro so we can have -* both the type-agnostic benefits of the macros while also being able to -* enforce that the return value is, in fact, checked. -*/ -static inline bool __must_check __must_check_overflow (bool overflow) -{ -return unlikely (overflow); -} - -/* -* For simplicity and code hygiene, the fallback code below insists on -* a, b and *d having the same type (similar to the min() and max() -* macros), whereas gcc's type-generic overflow checkers accept -* different types. Hence we don't just make check_add_overflow an -* alias for __builtin_add_overflow, but add type checks similar to -* below. -*/ -#define check_add_overflow (a, b, d) __must_check_overflow(({ \ - typeof(a) __a = (a); \ - typeof(b) __b = (b); \ - typeof(d) __d = (d); \ - (void) (&__a == &__b); \ - (void) (&__a == __d); \ - __builtin_add_overflow(__a, __b, __d); \ -})) -#define min_t (type,x,y) \ ({ type __x = (x); type __y = (y); __x < __y ? __x: __y; })#define max_t (type,x,y) \
libxfs/xfs_format.h +3 -0
@@ -176,6 +176,9 @@ typedef struct xfs_sb {xfs_ino_t sb_metadirino;/* metadata directory tree root */ +xfs_rgnumber_t sb_rgcount;/* number of realtime groups */ +xfs_rtxlen_t sb_rgextents;/* size of a realtime group in rtx */ +/* must be padded to 64 bit alignment */ } xfs_sb_t;
libxfs/xfs_rtgroup.c new file +149 -0
149 lines not on this page · raw message
libxfs/xfs_rtgroup.h new file +217 -0
217 lines not on this page · raw message
libxfs/xfs_sb.c +13 -0
@@ -707,6 +707,9 @@ __xfs_sb_from_disk( to->sb_metadirino =be64_to_cpu (from->sb_metadirino); else to->sb_metadirino = NULLFSINO; + + to->sb_rgcount =1 ; + to->sb_rgextents =0 ; }void
@@ -991,8 +994,18 @@ xfs_mount_sb_set_rextsize(struct xfs_mount *mp, struct xfs_sb *sbp) { + struct xfs_groups *rgs = &mp->m_groups[XG_TYPE_RTG]; + mp->m_rtxblklog =log2_if_power2 (sbp->sb_rextsize); mp->m_rtxblkmask =mask64_if_power2 (sbp->sb_rextsize); + + mp->m_rgblocks =0 ; + mp->m_rgblklog =0 ; + mp->m_rgblkmask = (uint64_t )-1 ; + + rgs->blocks =0 ; + rgs->blklog =0 ; + rgs->blkmask = (uint64_t )-1 ; }/*
libxfs/xfs_types.h +7 -1
@@ -9,10 +9,12 @@typedef uint32_t prid_t ;/* project ID */ typedef uint32_t xfs_agblock_t ;/* blockno in alloc. group */ +typedef uint32_t xfs_rgblock_t ;/* blockno in realtime group */ typedef uint32_t xfs_agino_t ;/* inode # within allocation grp */ typedef uint32_t xfs_extlen_t ;/* extent length in blocks */ typedef uint32_t xfs_rtxlen_t ;/* file extent length in rtextents */ typedef uint32_t xfs_agnumber_t ;/* allocation group number */ +typedef uint32_t xfs_rgnumber_t ;/* realtime group number */ typedef uint64_t xfs_extnum_t ;/* # of extents in a file */ typedef uint32_t xfs_aextnum_t ;/* # extents in an attribute fork */ typedef int64_t xfs_fsize_t ;/* bytes in a file */
@@ -53,7 +55,9 @@ typedef void * xfs_failaddr_t;#define NULLFILEOFF ((xfs_fileoff_t)-1)#define NULLAGBLOCK ((xfs_agblock_t)-1) +#define NULLRGBLOCK ((xfs_rgblock_t)-1)#define NULLAGNUMBER ((xfs_agnumber_t)-1) +#define NULLRGNUMBER ((xfs_rgnumber_t)-1)#define NULLCOMMITLSN ((xfs_lsn_t)-1)
@@ -214,11 +218,13 @@ enum xbtree_recpacking {enum xfs_group_type {XG_TYPE_AG , +XG_TYPE_RTG ,XG_TYPE_MAX , } __packed;#define XG_TYPE_STRINGS \ - { XG_TYPE_AG, "ag" } + { XG_TYPE_AG, "ag" }, \ + { XG_TYPE_RTG, "rtg" }/* * Type verifier functions
mkfs/xfs_mkfs.c +8 -0
@@ -3592,6 +3592,14 @@ sb_set_features(if (!fp->metadir) sbp->sb_bad_features2 = sbp->sb_features2; +/* +* This will be overriden later for real rtgroup file systems. For +* !rtgroups filesystems, we pretend that there's one huge group, just +* like __xfs_sb_from_disk does. +*/ + sbp->sb_rgcount =1 ; + sbp->sb_rgextents =0 ; +if (!fp->crcs_enabled)return ;
PATCH 2/52 xfs: define locking primitives for realtime groups
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
Source kernel commit: 0e4875b3fb24c5bfdf685876c76713cda5a23b65
Define helper functions to lock all metadata inodes related to a realtime group. There's not much to look at now, but this will become important when we add per-rtgroup metadata files and online fsck code for them.
--- libxfs/xfs_rtgroup.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ libxfs/xfs_rtgroup.h | 16 ++++++++++++++++ 2 files changed, 65 insertions(+)
libxfs/xfs_rtgroup.c +49 -0
@@ -147,3 +147,52 @@ xfs_update_last_rtgroup_size(xfs_rtgroup_rele (rtg);return 0 ; } + +/* Lock metadata inodes associated with this rt group. */ +void +xfs_rtgroup_lock ( +struct xfs_rtgroup *rtg, +unsigned int rtglock_flags) +{ +ASSERT (!(rtglock_flags & ~XFS_RTGLOCK_ALL_FLAGS )); +ASSERT (!(rtglock_flags &XFS_RTGLOCK_BITMAP_SHARED ) || + !(rtglock_flags &XFS_RTGLOCK_BITMAP )); + +if (rtglock_flags &XFS_RTGLOCK_BITMAP ) +xfs_rtbitmap_lock (rtg_mount (rtg)); +else if (rtglock_flags &XFS_RTGLOCK_BITMAP_SHARED ) +xfs_rtbitmap_lock_shared (rtg_mount (rtg),XFS_RBMLOCK_BITMAP ); +} + +/* Unlock metadata inodes associated with this rt group. */ +void +xfs_rtgroup_unlock ( +struct xfs_rtgroup *rtg, +unsigned int rtglock_flags) +{ +ASSERT (!(rtglock_flags & ~XFS_RTGLOCK_ALL_FLAGS )); +ASSERT (!(rtglock_flags &XFS_RTGLOCK_BITMAP_SHARED ) || + !(rtglock_flags &XFS_RTGLOCK_BITMAP )); + +if (rtglock_flags &XFS_RTGLOCK_BITMAP ) +xfs_rtbitmap_unlock (rtg_mount (rtg)); +else if (rtglock_flags &XFS_RTGLOCK_BITMAP_SHARED ) +xfs_rtbitmap_unlock_shared (rtg_mount (rtg),XFS_RBMLOCK_BITMAP ); +} + +/* +* Join realtime group metadata inodes to the transaction. The ILOCKs will be +* released on transaction commit. +*/ +void +xfs_rtgroup_trans_join ( +struct xfs_trans *tp, +struct xfs_rtgroup *rtg, +unsigned int rtglock_flags) +{ +ASSERT (!(rtglock_flags & ~XFS_RTGLOCK_ALL_FLAGS )); +ASSERT (!(rtglock_flags &XFS_RTGLOCK_BITMAP_SHARED )); + +if (rtglock_flags &XFS_RTGLOCK_BITMAP ) +xfs_rtbitmap_trans_join (tp); +}
libxfs/xfs_rtgroup.h +16 -0
@@ -197,6 +197,19 @@ xfs_rtxnum_t xfs_rtgroup_extents(struct xfs_mount *mp, xfs_rgnumber_t rgno);int xfs_update_last_rtgroup_size (struct xfs_mount *mp,xfs_rgnumber_t prev_rgcount); + +/* Lock the rt bitmap inode in exclusive mode */ +#define XFS_RTGLOCK_BITMAP (1U << 0) +/* Lock the rt bitmap inode in shared mode */ +#define XFS_RTGLOCK_BITMAP_SHARED (1U << 1) + +#define XFS_RTGLOCK_ALL_FLAGS (XFS_RTGLOCK_BITMAP | \ + XFS_RTGLOCK_BITMAP_SHARED) + +void xfs_rtgroup_lock (struct xfs_rtgroup *rtg,unsigned int rtglock_flags); +void xfs_rtgroup_unlock (struct xfs_rtgroup *rtg,unsigned int rtglock_flags); +void xfs_rtgroup_trans_join (struct xfs_trans *tp,struct xfs_rtgroup *rtg, +unsigned int rtglock_flags);#else static inline void xfs_free_rtgroups (struct xfs_mount *mp,xfs_rgnumber_t first_rgno,xfs_rgnumber_t end_rgno)
@@ -212,6 +225,9 @@ static inline int xfs_initialize_rtgroups(struct xfs_mount *mp,# define xfs_rtgroup_extents (mp, rgno) (0)# define xfs_update_last_rtgroup_size (mp, rgno) (-EOPNOTSUPP) +# define xfs_rtgroup_lock (rtg, gf) ((void)0) +# define xfs_rtgroup_unlock (rtg, gf) ((void)0) +# define xfs_rtgroup_trans_join (tp, rtg, gf) ((void)0)#endif /* CONFIG_XFS_RT */ #endif /* __LIBXFS_RTGROUP_H */
PATCH 3/52 xfs: add a lockdep class key for rtgroup inodes
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
Source kernel commit: c29237a65c8dbfade3c032763b66d495b8e8cb7a
Add a dynamic lockdep class key for rtgroup inodes. This will enable lockdep to deduce inconsistencies in the rtgroup metadata ILOCK locking order. Each class can have 8 subclasses, and for now we will only have 2 inodes per group. This enables rtgroup order and inode order checks when nesting ILOCKs.
--- libxfs/xfs_rtgroup.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+)
libxfs/xfs_rtgroup.c +52 -0
@@ -196,3 +196,55 @@ xfs_rtgroup_trans_join(if (rtglock_flags &XFS_RTGLOCK_BITMAP )xfs_rtbitmap_trans_join (tp); } + +#ifdef CONFIG_PROVE_LOCKING +static struct lock_class_key xfs_rtginode_lock_class; + +static int +xfs_rtginode_ilock_cmp_fn ( +const struct lockdep_map *m1, +const struct lockdep_map *m2) +{ +const struct xfs_inode *ip1 = + container_of(m1, struct xfs_inode, i_lock.dep_map); +const struct xfs_inode *ip2 = + container_of(m2, struct xfs_inode, i_lock.dep_map); + +if (ip1->i_projid < ip2->i_projid) +return -1 ; +if (ip1->i_projid > ip2->i_projid) +return 1 ; +return 0 ; +} + +static inline void +xfs_rtginode_ilock_print_fn ( +const struct lockdep_map *m) +{ +const struct xfs_inode *ip = + container_of(m, struct xfs_inode, i_lock.dep_map); + +printk (KERN_CONT " rgno=%u" , ip->i_projid); +} + +/* +* Most of the time each of the RTG inode locks are only taken one at a time. +* But when committing deferred ops, more than one of a kind can be taken. +* However, deferred rt ops will be committed in rgno order so there is no +* potential for deadlocks. The code here is needed to tell lockdep about this +* order. +*/ +static inline void +xfs_rtginode_lockdep_setup ( +struct xfs_inode *ip, +xfs_rgnumber_t rgno, +enum xfs_rtg_inodes type) +{ +lockdep_set_class_and_subclass (&ip->i_lock, &xfs_rtginode_lock_class, + type); +lock_set_cmp_fn (&ip->i_lock, xfs_rtginode_ilock_cmp_fn, + xfs_rtginode_ilock_print_fn); +} +#else +#define xfs_rtginode_lockdep_setup (ip, rgno, type) do { } while (0) +#endif /* CONFIG_PROVE_LOCKING */
PATCH 4/52 xfs: support caching rtgroup metadata inodes
In reply to Darrick J. WongFrom: Darrick J. Wong <[email protected]>
Source kernel commit: 65b1231b8cea7fbe7362dceecfda76026d335536
Create the necessary per-rtgroup infrastructure that we need to load metadata inodes into memory.
--- include/xfs_mount.h | 1 libxfs/init.c | 11 ++++ libxfs/libxfs_api_defs.h | 1 libxfs/xfs_rtgroup.c | 123 ++++++++++++++++++++++++++++++++++++++++++++++ libxfs/xfs_rtgroup.h | 27 ++++++++++ 5 files changed, 162 insertions(+), 1 deletion(-)
include/xfs_mount.h +1 -0
@@ -93,6 +93,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_metadirip;/* ptr to metadata directory */ +struct xfs_inode *m_rtdirip;/* ptr to realtime metadir */ struct xfs_buftarg *m_ddev_targp;struct xfs_buftarg *m_logdev_targp;struct xfs_buftarg *m_rtdev_targp;
libxfs/init.c +10 -1
@@ -846,8 +846,17 @@ libxfs_mount( }void -libxfs_rtmount_destroy (xfs_mount_t *mp) +libxfs_rtmount_destroy ( +struct xfs_mount *mp) { +struct xfs_rtgroup *rtg =NULL ; +unsigned int i; + +while ((rtg =xfs_rtgroup_next (mp, rtg))) { +for (i =0 ; i <XFS_RTGI_MAX ; i++) +libxfs_rtginode_irele (&rtg->rtg_inodes[i]); + } +libxfs_rtginode_irele (&mp->m_rtdirip);if (mp->m_rsumip)libxfs_irele (mp->m_rsumip);if (mp->m_rbmip)
libxfs/libxfs_api_defs.h +1 -0
@@ -277,6 +277,7 @@#define xfs_rtbitmap_getword libxfs_rtbitmap_getword#define xfs_rtbitmap_setword libxfs_rtbitmap_setword#define xfs_rtbitmap_wordcount libxfs_rtbitmap_wordcount +#define xfs_rtginode_irele libxfs_rtginode_irele#define xfs_rtgroup_alloc libxfs_rtgroup_alloc
libxfs/xfs_rtgroup.c +123 -0
132 lines not on this page · raw message
libxfs/xfs_rtgroup.h +27 -0
@@ -11,12 +11,23 @@struct xfs_mount ;struct xfs_trans ; +enum xfs_rtg_inodes { +XFS_RTGI_MAX , +}; + +#ifdef MAX_LOCKDEP_SUBCLASSES +static_assert (XFS_RTGI_MAX <=MAX_LOCKDEP_SUBCLASSES ); +#endif +/* * Realtime group incore structure, similar to the per-AG structure. */ struct xfs_rtgroup {struct xfs_group rtg_group; +/* per-rtgroup metadata inodes */ +struct xfs_inode *rtg_inodes[1 /* hack */ ]; +/* Number of blocks in this group */ xfs_rtxnum_t rtg_extents; };
@@ -210,6 +221,22 @@ void xfs_rtgroup_lock(struct xfs_rtgroup *rtg, unsigned int rtglock_flags);void xfs_rtgroup_unlock (struct xfs_rtgroup *rtg,unsigned int rtglock_flags);void xfs_rtgroup_trans_join (struct xfs_trans *tp,struct xfs_rtgroup *rtg,unsigned int rtglock_flags); + +int xfs_rtginode_mkdir_parent (struct xfs_mount *mp); +int xfs_rtginode_load_parent (struct xfs_trans *tp); + +const char *xfs_rtginode_name (enum xfs_rtg_inodes type); +enum xfs_metafile_type xfs_rtginode_metafile_type (enum xfs_rtg_inodes type); +bool xfs_rtginode_enabled (struct xfs_rtgroup *rtg,enum xfs_rtg_inodes type); +int xfs_rtginode_load (struct xfs_rtgroup *rtg,enum xfs_rtg_inodes type, +struct xfs_trans *tp); +void xfs_rtginode_irele (struct xfs_inode **ipp); + +static inline const char *xfs_rtginode_path (xfs_rgnumber_t rgno, +enum xfs_rtg_inodes type) +{ +return kasprintf (GFP_KERNEL ,"%u.%s" , rgno,xfs_rtginode_name (type)); +}#else static inline void xfs_free_rtgroups (struct xfs_mount *mp,xfs_rgnumber_t first_rgno,xfs_rgnumber_t end_rgno)