diff options
Diffstat (limited to 'fs/xfs/libxfs/xfs_ialloc.c')
-rw-r--r-- | fs/xfs/libxfs/xfs_ialloc.c | 99 |
1 files changed, 99 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 | } | ||