]>
Commit | Line | Data |
---|---|---|
1727fd17 DC |
1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* | |
3 | * Copyright (c) 2000-2002,2005 Silicon Graphics, Inc. | |
4 | * Copyright (C) 2017 Oracle. | |
5 | * All Rights Reserved. | |
6 | */ | |
7 | #include "libxfs_priv.h" | |
8 | #include "xfs_fs.h" | |
9 | #include "xfs_format.h" | |
10 | #include "xfs_log_format.h" | |
11 | #include "xfs_shared.h" | |
12 | #include "xfs_trans_resv.h" | |
13 | #include "xfs_bit.h" | |
14 | #include "xfs_sb.h" | |
15 | #include "xfs_mount.h" | |
16 | #include "xfs_defer.h" | |
17 | #include "xfs_inode.h" | |
18 | #include "xfs_btree.h" | |
19 | #include "xfs_rmap.h" | |
20 | #include "xfs_alloc_btree.h" | |
21 | #include "xfs_alloc.h" | |
22 | #include "xfs_ialloc.h" | |
23 | ||
24 | /* Find the size of the AG, in blocks. */ | |
25 | xfs_agblock_t | |
26 | xfs_ag_block_count( | |
27 | struct xfs_mount *mp, | |
28 | xfs_agnumber_t agno) | |
29 | { | |
30 | ASSERT(agno < mp->m_sb.sb_agcount); | |
31 | ||
32 | if (agno < mp->m_sb.sb_agcount - 1) | |
33 | return mp->m_sb.sb_agblocks; | |
34 | return mp->m_sb.sb_dblocks - (agno * mp->m_sb.sb_agblocks); | |
35 | } | |
36 | ||
37 | /* | |
38 | * Verify that an AG block number pointer neither points outside the AG | |
39 | * nor points at static metadata. | |
40 | */ | |
41 | bool | |
42 | xfs_verify_agbno( | |
43 | struct xfs_mount *mp, | |
44 | xfs_agnumber_t agno, | |
45 | xfs_agblock_t agbno) | |
46 | { | |
47 | xfs_agblock_t eoag; | |
48 | ||
49 | eoag = xfs_ag_block_count(mp, agno); | |
50 | if (agbno >= eoag) | |
51 | return false; | |
52 | if (agbno <= XFS_AGFL_BLOCK(mp)) | |
53 | return false; | |
54 | return true; | |
55 | } | |
56 | ||
57 | /* | |
58 | * Verify that an FS block number pointer neither points outside the | |
59 | * filesystem nor points at static AG metadata. | |
60 | */ | |
61 | bool | |
62 | xfs_verify_fsbno( | |
63 | struct xfs_mount *mp, | |
64 | xfs_fsblock_t fsbno) | |
65 | { | |
66 | xfs_agnumber_t agno = XFS_FSB_TO_AGNO(mp, fsbno); | |
67 | ||
68 | if (agno >= mp->m_sb.sb_agcount) | |
69 | return false; | |
70 | return xfs_verify_agbno(mp, agno, XFS_FSB_TO_AGBNO(mp, fsbno)); | |
71 | } | |
72 | ||
73 | /* Calculate the first and last possible inode number in an AG. */ | |
74 | void | |
75 | xfs_agino_range( | |
76 | struct xfs_mount *mp, | |
77 | xfs_agnumber_t agno, | |
78 | xfs_agino_t *first, | |
79 | xfs_agino_t *last) | |
80 | { | |
81 | xfs_agblock_t bno; | |
82 | xfs_agblock_t eoag; | |
83 | ||
84 | eoag = xfs_ag_block_count(mp, agno); | |
85 | ||
86 | /* | |
87 | * Calculate the first inode, which will be in the first | |
88 | * cluster-aligned block after the AGFL. | |
89 | */ | |
90 | bno = round_up(XFS_AGFL_BLOCK(mp) + 1, | |
91 | xfs_ialloc_cluster_alignment(mp)); | |
92 | *first = XFS_OFFBNO_TO_AGINO(mp, bno, 0); | |
93 | ||
94 | /* | |
95 | * Calculate the last inode, which will be at the end of the | |
96 | * last (aligned) cluster that can be allocated in the AG. | |
97 | */ | |
98 | bno = round_down(eoag, xfs_ialloc_cluster_alignment(mp)); | |
99 | *last = XFS_OFFBNO_TO_AGINO(mp, bno, 0) - 1; | |
100 | } | |
101 | ||
102 | /* | |
103 | * Verify that an AG inode number pointer neither points outside the AG | |
104 | * nor points at static metadata. | |
105 | */ | |
106 | bool | |
107 | xfs_verify_agino( | |
108 | struct xfs_mount *mp, | |
109 | xfs_agnumber_t agno, | |
110 | xfs_agino_t agino) | |
111 | { | |
112 | xfs_agino_t first; | |
113 | xfs_agino_t last; | |
114 | ||
115 | xfs_agino_range(mp, agno, &first, &last); | |
116 | return agino >= first && agino <= last; | |
117 | } | |
118 | ||
119 | /* | |
120 | * Verify that an FS inode number pointer neither points outside the | |
121 | * filesystem nor points at static AG metadata. | |
122 | */ | |
123 | bool | |
124 | xfs_verify_ino( | |
125 | struct xfs_mount *mp, | |
126 | xfs_ino_t ino) | |
127 | { | |
128 | xfs_agnumber_t agno = XFS_INO_TO_AGNO(mp, ino); | |
129 | xfs_agino_t agino = XFS_INO_TO_AGINO(mp, ino); | |
130 | ||
131 | if (agno >= mp->m_sb.sb_agcount) | |
132 | return false; | |
133 | if (XFS_AGINO_TO_INO(mp, agno, agino) != ino) | |
134 | return false; | |
135 | return xfs_verify_agino(mp, agno, agino); | |
136 | } | |
137 | ||
138 | /* Is this an internal inode number? */ | |
139 | bool | |
140 | xfs_internal_inum( | |
141 | struct xfs_mount *mp, | |
142 | xfs_ino_t ino) | |
143 | { | |
144 | return ino == mp->m_sb.sb_rbmino || ino == mp->m_sb.sb_rsumino || | |
145 | (xfs_sb_version_hasquota(&mp->m_sb) && | |
146 | xfs_is_quota_inode(&mp->m_sb, ino)); | |
147 | } | |
148 | ||
149 | /* | |
150 | * Verify that a directory entry's inode number doesn't point at an internal | |
151 | * inode, empty space, or static AG metadata. | |
152 | */ | |
153 | bool | |
154 | xfs_verify_dir_ino( | |
155 | struct xfs_mount *mp, | |
156 | xfs_ino_t ino) | |
157 | { | |
158 | if (xfs_internal_inum(mp, ino)) | |
159 | return false; | |
160 | return xfs_verify_ino(mp, ino); | |
161 | } | |
162 | ||
163 | /* | |
164 | * Verify that an realtime block number pointer doesn't point off the | |
165 | * end of the realtime device. | |
166 | */ | |
167 | bool | |
168 | xfs_verify_rtbno( | |
169 | struct xfs_mount *mp, | |
170 | xfs_rtblock_t rtbno) | |
171 | { | |
172 | return rtbno < mp->m_sb.sb_rblocks; | |
173 | } |