summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDarrick J. Wong <darrick.wong@oracle.com>2017-10-18 00:37:34 -0400
committerDarrick J. Wong <darrick.wong@oracle.com>2017-10-26 18:38:23 -0400
commit91fb9afc0847926ef6ea7695b8125c8fbe7974d6 (patch)
tree3081f56bd69cad0fcd0906c80a151a8dd463ffca
parent52c732eee78b47ac2eb828b1c7fa611cd37b0090 (diff)
xfs: create inode pointer verifiers
Create some helper functions to check that inode pointers point to somewhere within the filesystem and not at the static AG metadata. Move xfs_internal_inum and create a directory inode check function. We will use these functions in scrub and elsewhere. Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com> Reviewed-by: Dave Chinner <dchinner@redhat.com>
-rw-r--r--fs/xfs/libxfs/xfs_dir2.c19
-rw-r--r--fs/xfs/libxfs/xfs_ialloc.c90
-rw-r--r--fs/xfs/libxfs/xfs_ialloc.h7
-rw-r--r--fs/xfs/xfs_itable.c10
-rw-r--r--fs/xfs/xfs_itable.h2
5 files changed, 100 insertions, 28 deletions
diff --git a/fs/xfs/libxfs/xfs_dir2.c b/fs/xfs/libxfs/xfs_dir2.c
index ccf9783fd3f0..ee5e9160eb01 100644
--- a/fs/xfs/libxfs/xfs_dir2.c
+++ b/fs/xfs/libxfs/xfs_dir2.c
@@ -30,6 +30,7 @@
30#include "xfs_bmap.h" 30#include "xfs_bmap.h"
31#include "xfs_dir2.h" 31#include "xfs_dir2.h"
32#include "xfs_dir2_priv.h" 32#include "xfs_dir2_priv.h"
33#include "xfs_ialloc.h"
33#include "xfs_error.h" 34#include "xfs_error.h"
34#include "xfs_trace.h" 35#include "xfs_trace.h"
35 36
@@ -202,22 +203,8 @@ xfs_dir_ino_validate(
202 xfs_mount_t *mp, 203 xfs_mount_t *mp,
203 xfs_ino_t ino) 204 xfs_ino_t ino)
204{ 205{
205 xfs_agblock_t agblkno; 206 bool ino_ok = xfs_verify_dir_ino(mp, ino);
206 xfs_agino_t agino; 207
207 xfs_agnumber_t agno;
208 int ino_ok;
209 int ioff;
210
211 agno = XFS_INO_TO_AGNO(mp, ino);
212 agblkno = XFS_INO_TO_AGBNO(mp, ino);
213 ioff = XFS_INO_TO_OFFSET(mp, ino);
214 agino = XFS_OFFBNO_TO_AGINO(mp, agblkno, ioff);
215 ino_ok =
216 agno < mp->m_sb.sb_agcount &&
217 agblkno < mp->m_sb.sb_agblocks &&
218 agblkno != 0 &&
219 ioff < (1 << mp->m_sb.sb_inopblog) &&
220 XFS_AGINO_TO_INO(mp, agno, agino) == ino;
221 if (unlikely(XFS_TEST_ERROR(!ino_ok, mp, XFS_ERRTAG_DIR_INO_VALIDATE))) { 208 if (unlikely(XFS_TEST_ERROR(!ino_ok, mp, XFS_ERRTAG_DIR_INO_VALIDATE))) {
222 xfs_warn(mp, "Invalid inode number 0x%Lx", 209 xfs_warn(mp, "Invalid inode number 0x%Lx",
223 (unsigned long long) ino); 210 (unsigned long long) ino);
diff --git a/fs/xfs/libxfs/xfs_ialloc.c b/fs/xfs/libxfs/xfs_ialloc.c
index dfd643909f85..e11f8af8a725 100644
--- a/fs/xfs/libxfs/xfs_ialloc.c
+++ b/fs/xfs/libxfs/xfs_ialloc.c
@@ -2664,3 +2664,93 @@ xfs_ialloc_pagi_init(
2664 xfs_trans_brelse(tp, bp); 2664 xfs_trans_brelse(tp, bp);
2665 return 0; 2665 return 0;
2666} 2666}
2667
2668/* Calculate the first and last possible inode number in an AG. */
2669void
2670xfs_ialloc_agino_range(
2671 struct xfs_mount *mp,
2672 xfs_agnumber_t agno,
2673 xfs_agino_t *first,
2674 xfs_agino_t *last)
2675{
2676 xfs_agblock_t bno;
2677 xfs_agblock_t eoag;
2678
2679 eoag = xfs_ag_block_count(mp, agno);
2680
2681 /*
2682 * Calculate the first inode, which will be in the first
2683 * cluster-aligned block after the AGFL.
2684 */
2685 bno = round_up(XFS_AGFL_BLOCK(mp) + 1,
2686 xfs_ialloc_cluster_alignment(mp));
2687 *first = XFS_OFFBNO_TO_AGINO(mp, bno, 0);
2688
2689 /*
2690 * Calculate the last inode, which will be at the end of the
2691 * last (aligned) cluster that can be allocated in the AG.
2692 */
2693 bno = round_down(eoag, xfs_ialloc_cluster_alignment(mp));
2694 *last = XFS_OFFBNO_TO_AGINO(mp, bno, 0) - 1;
2695}
2696
2697/*
2698 * Verify that an AG inode number pointer neither points outside the AG
2699 * nor points at static metadata.
2700 */
2701bool
2702xfs_verify_agino(
2703 struct xfs_mount *mp,
2704 xfs_agnumber_t agno,
2705 xfs_agino_t agino)
2706{
2707 xfs_agino_t first;
2708 xfs_agino_t last;
2709
2710 xfs_ialloc_agino_range(mp, agno, &first, &last);
2711 return agino >= first && agino <= last;
2712}
2713
2714/*
2715 * Verify that an FS inode number pointer neither points outside the
2716 * filesystem nor points at static AG metadata.
2717 */
2718bool
2719xfs_verify_ino(
2720 struct xfs_mount *mp,
2721 xfs_ino_t ino)
2722{
2723 xfs_agnumber_t agno = XFS_INO_TO_AGNO(mp, ino);
2724 xfs_agino_t agino = XFS_INO_TO_AGINO(mp, ino);
2725
2726 if (agno >= mp->m_sb.sb_agcount)
2727 return false;
2728 if (XFS_AGINO_TO_INO(mp, agno, agino) != ino)
2729 return false;
2730 return xfs_verify_agino(mp, agno, agino);
2731}
2732
2733/* Is this an internal inode number? */
2734bool
2735xfs_internal_inum(
2736 struct xfs_mount *mp,
2737 xfs_ino_t ino)
2738{
2739 return ino == mp->m_sb.sb_rbmino || ino == mp->m_sb.sb_rsumino ||
2740 (xfs_sb_version_hasquota(&mp->m_sb) &&
2741 xfs_is_quota_inode(&mp->m_sb, ino));
2742}
2743
2744/*
2745 * Verify that a directory entry's inode number doesn't point at an internal
2746 * inode, empty space, or static AG metadata.
2747 */
2748bool
2749xfs_verify_dir_ino(
2750 struct xfs_mount *mp,
2751 xfs_ino_t ino)
2752{
2753 if (xfs_internal_inum(mp, ino))
2754 return false;
2755 return xfs_verify_ino(mp, ino);
2756}
diff --git a/fs/xfs/libxfs/xfs_ialloc.h b/fs/xfs/libxfs/xfs_ialloc.h
index b32cfb5aeb5b..d2bdcd5e7312 100644
--- a/fs/xfs/libxfs/xfs_ialloc.h
+++ b/fs/xfs/libxfs/xfs_ialloc.h
@@ -173,5 +173,12 @@ void xfs_inobt_btrec_to_irec(struct xfs_mount *mp, union xfs_btree_rec *rec,
173 struct xfs_inobt_rec_incore *irec); 173 struct xfs_inobt_rec_incore *irec);
174 174
175int xfs_ialloc_cluster_alignment(struct xfs_mount *mp); 175int xfs_ialloc_cluster_alignment(struct xfs_mount *mp);
176void xfs_ialloc_agino_range(struct xfs_mount *mp, xfs_agnumber_t agno,
177 xfs_agino_t *first, xfs_agino_t *last);
178bool xfs_verify_agino(struct xfs_mount *mp, xfs_agnumber_t agno,
179 xfs_agino_t agino);
180bool xfs_verify_ino(struct xfs_mount *mp, xfs_ino_t ino);
181bool xfs_internal_inum(struct xfs_mount *mp, xfs_ino_t ino);
182bool xfs_verify_dir_ino(struct xfs_mount *mp, xfs_ino_t ino);
176 183
177#endif /* __XFS_IALLOC_H__ */ 184#endif /* __XFS_IALLOC_H__ */
diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c
index c393a2f6d8c3..0172d0b72c95 100644
--- a/fs/xfs/xfs_itable.c
+++ b/fs/xfs/xfs_itable.c
@@ -31,16 +31,6 @@
31#include "xfs_trace.h" 31#include "xfs_trace.h"
32#include "xfs_icache.h" 32#include "xfs_icache.h"
33 33
34int
35xfs_internal_inum(
36 xfs_mount_t *mp,
37 xfs_ino_t ino)
38{
39 return (ino == mp->m_sb.sb_rbmino || ino == mp->m_sb.sb_rsumino ||
40 (xfs_sb_version_hasquota(&mp->m_sb) &&
41 xfs_is_quota_inode(&mp->m_sb, ino)));
42}
43
44/* 34/*
45 * Return stat information for one inode. 35 * Return stat information for one inode.
46 * Return 0 if ok, else errno. 36 * Return 0 if ok, else errno.
diff --git a/fs/xfs/xfs_itable.h b/fs/xfs/xfs_itable.h
index 17e86e0541af..6ea8b3912fa4 100644
--- a/fs/xfs/xfs_itable.h
+++ b/fs/xfs/xfs_itable.h
@@ -96,6 +96,4 @@ xfs_inumbers(
96 void __user *buffer, /* buffer with inode info */ 96 void __user *buffer, /* buffer with inode info */
97 inumbers_fmt_pf formatter); 97 inumbers_fmt_pf formatter);
98 98
99int xfs_internal_inum(struct xfs_mount *mp, xfs_ino_t ino);
100
101#endif /* __XFS_ITABLE_H__ */ 99#endif /* __XFS_ITABLE_H__ */