Linux-libre 5.3.12-gnu
[librecmc/linux-libre.git] / fs / xfs / libxfs / xfs_types.c
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 "xfs.h"
8 #include "xfs_fs.h"
9 #include "xfs_format.h"
10 #include "xfs_shared.h"
11 #include "xfs_trans_resv.h"
12 #include "xfs_bit.h"
13 #include "xfs_mount.h"
14
15 /* Find the size of the AG, in blocks. */
16 xfs_agblock_t
17 xfs_ag_block_count(
18         struct xfs_mount        *mp,
19         xfs_agnumber_t          agno)
20 {
21         ASSERT(agno < mp->m_sb.sb_agcount);
22
23         if (agno < mp->m_sb.sb_agcount - 1)
24                 return mp->m_sb.sb_agblocks;
25         return mp->m_sb.sb_dblocks - (agno * mp->m_sb.sb_agblocks);
26 }
27
28 /*
29  * Verify that an AG block number pointer neither points outside the AG
30  * nor points at static metadata.
31  */
32 bool
33 xfs_verify_agbno(
34         struct xfs_mount        *mp,
35         xfs_agnumber_t          agno,
36         xfs_agblock_t           agbno)
37 {
38         xfs_agblock_t           eoag;
39
40         eoag = xfs_ag_block_count(mp, agno);
41         if (agbno >= eoag)
42                 return false;
43         if (agbno <= XFS_AGFL_BLOCK(mp))
44                 return false;
45         return true;
46 }
47
48 /*
49  * Verify that an FS block number pointer neither points outside the
50  * filesystem nor points at static AG metadata.
51  */
52 bool
53 xfs_verify_fsbno(
54         struct xfs_mount        *mp,
55         xfs_fsblock_t           fsbno)
56 {
57         xfs_agnumber_t          agno = XFS_FSB_TO_AGNO(mp, fsbno);
58
59         if (agno >= mp->m_sb.sb_agcount)
60                 return false;
61         return xfs_verify_agbno(mp, agno, XFS_FSB_TO_AGBNO(mp, fsbno));
62 }
63
64 /* Calculate the first and last possible inode number in an AG. */
65 void
66 xfs_agino_range(
67         struct xfs_mount        *mp,
68         xfs_agnumber_t          agno,
69         xfs_agino_t             *first,
70         xfs_agino_t             *last)
71 {
72         xfs_agblock_t           bno;
73         xfs_agblock_t           eoag;
74
75         eoag = xfs_ag_block_count(mp, agno);
76
77         /*
78          * Calculate the first inode, which will be in the first
79          * cluster-aligned block after the AGFL.
80          */
81         bno = round_up(XFS_AGFL_BLOCK(mp) + 1, M_IGEO(mp)->cluster_align);
82         *first = XFS_AGB_TO_AGINO(mp, bno);
83
84         /*
85          * Calculate the last inode, which will be at the end of the
86          * last (aligned) cluster that can be allocated in the AG.
87          */
88         bno = round_down(eoag, M_IGEO(mp)->cluster_align);
89         *last = XFS_AGB_TO_AGINO(mp, bno) - 1;
90 }
91
92 /*
93  * Verify that an AG inode number pointer neither points outside the AG
94  * nor points at static metadata.
95  */
96 bool
97 xfs_verify_agino(
98         struct xfs_mount        *mp,
99         xfs_agnumber_t          agno,
100         xfs_agino_t             agino)
101 {
102         xfs_agino_t             first;
103         xfs_agino_t             last;
104
105         xfs_agino_range(mp, agno, &first, &last);
106         return agino >= first && agino <= last;
107 }
108
109 /*
110  * Verify that an AG inode number pointer neither points outside the AG
111  * nor points at static metadata, or is NULLAGINO.
112  */
113 bool
114 xfs_verify_agino_or_null(
115         struct xfs_mount        *mp,
116         xfs_agnumber_t          agno,
117         xfs_agino_t             agino)
118 {
119         return agino == NULLAGINO || xfs_verify_agino(mp, agno, agino);
120 }
121
122 /*
123  * Verify that an FS inode number pointer neither points outside the
124  * filesystem nor points at static AG metadata.
125  */
126 bool
127 xfs_verify_ino(
128         struct xfs_mount        *mp,
129         xfs_ino_t               ino)
130 {
131         xfs_agnumber_t          agno = XFS_INO_TO_AGNO(mp, ino);
132         xfs_agino_t             agino = XFS_INO_TO_AGINO(mp, ino);
133
134         if (agno >= mp->m_sb.sb_agcount)
135                 return false;
136         if (XFS_AGINO_TO_INO(mp, agno, agino) != ino)
137                 return false;
138         return xfs_verify_agino(mp, agno, agino);
139 }
140
141 /* Is this an internal inode number? */
142 bool
143 xfs_internal_inum(
144         struct xfs_mount        *mp,
145         xfs_ino_t               ino)
146 {
147         return ino == mp->m_sb.sb_rbmino || ino == mp->m_sb.sb_rsumino ||
148                 (xfs_sb_version_hasquota(&mp->m_sb) &&
149                  xfs_is_quota_inode(&mp->m_sb, ino));
150 }
151
152 /*
153  * Verify that a directory entry's inode number doesn't point at an internal
154  * inode, empty space, or static AG metadata.
155  */
156 bool
157 xfs_verify_dir_ino(
158         struct xfs_mount        *mp,
159         xfs_ino_t               ino)
160 {
161         if (xfs_internal_inum(mp, ino))
162                 return false;
163         return xfs_verify_ino(mp, ino);
164 }
165
166 /*
167  * Verify that an realtime block number pointer doesn't point off the
168  * end of the realtime device.
169  */
170 bool
171 xfs_verify_rtbno(
172         struct xfs_mount        *mp,
173         xfs_rtblock_t           rtbno)
174 {
175         return rtbno < mp->m_sb.sb_rblocks;
176 }
177
178 /* Calculate the range of valid icount values. */
179 void
180 xfs_icount_range(
181         struct xfs_mount        *mp,
182         unsigned long long      *min,
183         unsigned long long      *max)
184 {
185         unsigned long long      nr_inos = 0;
186         xfs_agnumber_t          agno;
187
188         /* root, rtbitmap, rtsum all live in the first chunk */
189         *min = XFS_INODES_PER_CHUNK;
190
191         for (agno = 0; agno < mp->m_sb.sb_agcount; agno++) {
192                 xfs_agino_t     first, last;
193
194                 xfs_agino_range(mp, agno, &first, &last);
195                 nr_inos += last - first + 1;
196         }
197         *max = nr_inos;
198 }
199
200 /* Sanity-checking of inode counts. */
201 bool
202 xfs_verify_icount(
203         struct xfs_mount        *mp,
204         unsigned long long      icount)
205 {
206         unsigned long long      min, max;
207
208         xfs_icount_range(mp, &min, &max);
209         return icount >= min && icount <= max;
210 }
211
212 /* Sanity-checking of dir/attr block offsets. */
213 bool
214 xfs_verify_dablk(
215         struct xfs_mount        *mp,
216         xfs_fileoff_t           dabno)
217 {
218         xfs_dablk_t             max_dablk = -1U;
219
220         return dabno <= max_dablk;
221 }