diff options
author | Darrick J. Wong <darrick.wong@oracle.com> | 2018-01-16 21:52:12 -0500 |
---|---|---|
committer | Darrick J. Wong <darrick.wong@oracle.com> | 2018-01-18 00:00:44 -0500 |
commit | 2e001266b67c865ad904e1889658282d0773b207 (patch) | |
tree | 337e892382421bc1570a2611884b98f41003a648 | |
parent | ce1d802e6a889b8ee53b3444c6d7e8cfecadac50 (diff) |
xfs: add scrub cross-referencing helpers for the inode btrees
Add a couple of functions to the inode btrees that will be used
to cross-reference metadata against the inobt.
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
-rw-r--r-- | fs/xfs/libxfs/xfs_ialloc.c | 99 | ||||
-rw-r--r-- | fs/xfs/libxfs/xfs_ialloc.h | 6 |
2 files changed, 105 insertions, 0 deletions
diff --git a/fs/xfs/libxfs/xfs_ialloc.c b/fs/xfs/libxfs/xfs_ialloc.c index c01ed9cfc5ae..3625d1da7462 100644 --- a/fs/xfs/libxfs/xfs_ialloc.c +++ b/fs/xfs/libxfs/xfs_ialloc.c | |||
@@ -2753,3 +2753,102 @@ xfs_verify_dir_ino( | |||
2753 | return false; | 2753 | return false; |
2754 | return xfs_verify_ino(mp, ino); | 2754 | return xfs_verify_ino(mp, ino); |
2755 | } | 2755 | } |
2756 | |||
2757 | /* Is there an inode record covering a given range of inode numbers? */ | ||
2758 | int | ||
2759 | xfs_ialloc_has_inode_record( | ||
2760 | struct xfs_btree_cur *cur, | ||
2761 | xfs_agino_t low, | ||
2762 | xfs_agino_t high, | ||
2763 | bool *exists) | ||
2764 | { | ||
2765 | struct xfs_inobt_rec_incore irec; | ||
2766 | xfs_agino_t agino; | ||
2767 | uint16_t holemask; | ||
2768 | int has_record; | ||
2769 | int i; | ||
2770 | int error; | ||
2771 | |||
2772 | *exists = false; | ||
2773 | error = xfs_inobt_lookup(cur, low, XFS_LOOKUP_LE, &has_record); | ||
2774 | while (error == 0 && has_record) { | ||
2775 | error = xfs_inobt_get_rec(cur, &irec, &has_record); | ||
2776 | if (error || irec.ir_startino > high) | ||
2777 | break; | ||
2778 | |||
2779 | agino = irec.ir_startino; | ||
2780 | holemask = irec.ir_holemask; | ||
2781 | for (i = 0; i < XFS_INOBT_HOLEMASK_BITS; holemask >>= 1, | ||
2782 | i++, agino += XFS_INODES_PER_HOLEMASK_BIT) { | ||
2783 | if (holemask & 1) | ||
2784 | continue; | ||
2785 | if (agino + XFS_INODES_PER_HOLEMASK_BIT > low && | ||
2786 | agino <= high) { | ||
2787 | *exists = true; | ||
2788 | return 0; | ||
2789 | } | ||
2790 | } | ||
2791 | |||
2792 | error = xfs_btree_increment(cur, 0, &has_record); | ||
2793 | } | ||
2794 | return error; | ||
2795 | } | ||
2796 | |||
2797 | /* Is there an inode record covering a given extent? */ | ||
2798 | int | ||
2799 | xfs_ialloc_has_inodes_at_extent( | ||
2800 | struct xfs_btree_cur *cur, | ||
2801 | xfs_agblock_t bno, | ||
2802 | xfs_extlen_t len, | ||
2803 | bool *exists) | ||
2804 | { | ||
2805 | xfs_agino_t low; | ||
2806 | xfs_agino_t high; | ||
2807 | |||
2808 | low = XFS_OFFBNO_TO_AGINO(cur->bc_mp, bno, 0); | ||
2809 | high = XFS_OFFBNO_TO_AGINO(cur->bc_mp, bno + len, 0) - 1; | ||
2810 | |||
2811 | return xfs_ialloc_has_inode_record(cur, low, high, exists); | ||
2812 | } | ||
2813 | |||
2814 | struct xfs_ialloc_count_inodes { | ||
2815 | xfs_agino_t count; | ||
2816 | xfs_agino_t freecount; | ||
2817 | }; | ||
2818 | |||
2819 | /* Record inode counts across all inobt records. */ | ||
2820 | STATIC int | ||
2821 | xfs_ialloc_count_inodes_rec( | ||
2822 | struct xfs_btree_cur *cur, | ||
2823 | union xfs_btree_rec *rec, | ||
2824 | void *priv) | ||
2825 | { | ||
2826 | struct xfs_inobt_rec_incore irec; | ||
2827 | struct xfs_ialloc_count_inodes *ci = priv; | ||
2828 | |||
2829 | xfs_inobt_btrec_to_irec(cur->bc_mp, rec, &irec); | ||
2830 | ci->count += irec.ir_count; | ||
2831 | ci->freecount += irec.ir_freecount; | ||
2832 | |||
2833 | return 0; | ||
2834 | } | ||
2835 | |||
2836 | /* Count allocated and free inodes under an inobt. */ | ||
2837 | int | ||
2838 | xfs_ialloc_count_inodes( | ||
2839 | struct xfs_btree_cur *cur, | ||
2840 | xfs_agino_t *count, | ||
2841 | xfs_agino_t *freecount) | ||
2842 | { | ||
2843 | struct xfs_ialloc_count_inodes ci = {0}; | ||
2844 | int error; | ||
2845 | |||
2846 | ASSERT(cur->bc_btnum == XFS_BTNUM_INO); | ||
2847 | error = xfs_btree_query_all(cur, xfs_ialloc_count_inodes_rec, &ci); | ||
2848 | if (error) | ||
2849 | return error; | ||
2850 | |||
2851 | *count = ci.count; | ||
2852 | *freecount = ci.freecount; | ||
2853 | return 0; | ||
2854 | } | ||
diff --git a/fs/xfs/libxfs/xfs_ialloc.h b/fs/xfs/libxfs/xfs_ialloc.h index 66a8de0b1caa..c5402bb4ce0c 100644 --- a/fs/xfs/libxfs/xfs_ialloc.h +++ b/fs/xfs/libxfs/xfs_ialloc.h | |||
@@ -170,6 +170,12 @@ int xfs_read_agi(struct xfs_mount *mp, struct xfs_trans *tp, | |||
170 | union xfs_btree_rec; | 170 | union xfs_btree_rec; |
171 | void xfs_inobt_btrec_to_irec(struct xfs_mount *mp, union xfs_btree_rec *rec, | 171 | void xfs_inobt_btrec_to_irec(struct xfs_mount *mp, union xfs_btree_rec *rec, |
172 | struct xfs_inobt_rec_incore *irec); | 172 | struct xfs_inobt_rec_incore *irec); |
173 | int xfs_ialloc_has_inodes_at_extent(struct xfs_btree_cur *cur, | ||
174 | xfs_agblock_t bno, xfs_extlen_t len, bool *exists); | ||
175 | int xfs_ialloc_has_inode_record(struct xfs_btree_cur *cur, xfs_agino_t low, | ||
176 | xfs_agino_t high, bool *exists); | ||
177 | int xfs_ialloc_count_inodes(struct xfs_btree_cur *cur, xfs_agino_t *count, | ||
178 | xfs_agino_t *freecount); | ||
173 | 179 | ||
174 | int xfs_ialloc_cluster_alignment(struct xfs_mount *mp); | 180 | int xfs_ialloc_cluster_alignment(struct xfs_mount *mp); |
175 | void xfs_ialloc_agino_range(struct xfs_mount *mp, xfs_agnumber_t agno, | 181 | void xfs_ialloc_agino_range(struct xfs_mount *mp, xfs_agnumber_t agno, |