]> Git Repo - linux.git/blob - fs/xfs/libxfs/xfs_types.c
Linux 6.14-rc3
[linux.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 #include "xfs_ag.h"
15 #include "xfs_rtbitmap.h"
16 #include "xfs_rtgroup.h"
17
18
19 /*
20  * Verify that an AG block number pointer neither points outside the AG
21  * nor points at static metadata.
22  */
23 static inline bool
24 xfs_verify_agno_agbno(
25         struct xfs_mount        *mp,
26         xfs_agnumber_t          agno,
27         xfs_agblock_t           agbno)
28 {
29         xfs_agblock_t           eoag;
30
31         eoag = xfs_ag_block_count(mp, agno);
32         if (agbno >= eoag)
33                 return false;
34         if (agbno <= XFS_AGFL_BLOCK(mp))
35                 return false;
36         return true;
37 }
38
39 /*
40  * Verify that an FS block number pointer neither points outside the
41  * filesystem nor points at static AG metadata.
42  */
43 inline bool
44 xfs_verify_fsbno(
45         struct xfs_mount        *mp,
46         xfs_fsblock_t           fsbno)
47 {
48         xfs_agnumber_t          agno = XFS_FSB_TO_AGNO(mp, fsbno);
49
50         if (agno >= mp->m_sb.sb_agcount)
51                 return false;
52         return xfs_verify_agno_agbno(mp, agno, XFS_FSB_TO_AGBNO(mp, fsbno));
53 }
54
55 /*
56  * Verify that a data device extent is fully contained inside the filesystem,
57  * does not cross an AG boundary, and does not point at static metadata.
58  */
59 bool
60 xfs_verify_fsbext(
61         struct xfs_mount        *mp,
62         xfs_fsblock_t           fsbno,
63         xfs_fsblock_t           len)
64 {
65         if (fsbno + len <= fsbno)
66                 return false;
67
68         if (!xfs_verify_fsbno(mp, fsbno))
69                 return false;
70
71         if (!xfs_verify_fsbno(mp, fsbno + len - 1))
72                 return false;
73
74         return  XFS_FSB_TO_AGNO(mp, fsbno) ==
75                 XFS_FSB_TO_AGNO(mp, fsbno + len - 1);
76 }
77
78 /*
79  * Verify that an AG inode number pointer neither points outside the AG
80  * nor points at static metadata.
81  */
82 static inline bool
83 xfs_verify_agno_agino(
84         struct xfs_mount        *mp,
85         xfs_agnumber_t          agno,
86         xfs_agino_t             agino)
87 {
88         xfs_agino_t             first;
89         xfs_agino_t             last;
90
91         xfs_agino_range(mp, agno, &first, &last);
92         return agino >= first && agino <= last;
93 }
94
95 /*
96  * Verify that an FS inode number pointer neither points outside the
97  * filesystem nor points at static AG metadata.
98  */
99 inline bool
100 xfs_verify_ino(
101         struct xfs_mount        *mp,
102         xfs_ino_t               ino)
103 {
104         xfs_agnumber_t          agno = XFS_INO_TO_AGNO(mp, ino);
105         xfs_agino_t             agino = XFS_INO_TO_AGINO(mp, ino);
106
107         if (agno >= mp->m_sb.sb_agcount)
108                 return false;
109         if (XFS_AGINO_TO_INO(mp, agno, agino) != ino)
110                 return false;
111         return xfs_verify_agno_agino(mp, agno, agino);
112 }
113
114 /* Is this an internal inode number? */
115 inline bool
116 xfs_is_sb_inum(
117         struct xfs_mount        *mp,
118         xfs_ino_t               ino)
119 {
120         return ino == mp->m_sb.sb_rbmino || ino == mp->m_sb.sb_rsumino ||
121                 (xfs_has_quota(mp) &&
122                  xfs_is_quota_inode(&mp->m_sb, ino));
123 }
124
125 /*
126  * Verify that a directory entry's inode number doesn't point at an internal
127  * inode, empty space, or static AG metadata.
128  */
129 bool
130 xfs_verify_dir_ino(
131         struct xfs_mount        *mp,
132         xfs_ino_t               ino)
133 {
134         if (xfs_is_sb_inum(mp, ino))
135                 return false;
136         return xfs_verify_ino(mp, ino);
137 }
138
139 /*
140  * Verify that a realtime block number pointer neither points outside the
141  * allocatable areas of the rtgroup nor off the end of the realtime
142  * device.
143  */
144 inline bool
145 xfs_verify_rtbno(
146         struct xfs_mount        *mp,
147         xfs_rtblock_t           rtbno)
148 {
149         if (xfs_has_rtgroups(mp)) {
150                 xfs_rgnumber_t  rgno = xfs_rtb_to_rgno(mp, rtbno);
151                 xfs_rtxnum_t    rtx = xfs_rtb_to_rtx(mp, rtbno);
152
153                 if (rgno >= mp->m_sb.sb_rgcount)
154                         return false;
155                 if (rtx >= xfs_rtgroup_extents(mp, rgno))
156                         return false;
157                 if (xfs_has_rtsb(mp) && rgno == 0 && rtx == 0)
158                         return false;
159                 return true;
160         }
161
162         return rtbno < mp->m_sb.sb_rblocks;
163 }
164
165 /*
166  * Verify that an allocated realtime device extent neither points outside
167  * allocatable areas of the rtgroup, across an rtgroup boundary, nor off the
168  * end of the realtime device.
169  */
170 bool
171 xfs_verify_rtbext(
172         struct xfs_mount        *mp,
173         xfs_rtblock_t           rtbno,
174         xfs_filblks_t           len)
175 {
176         if (rtbno + len <= rtbno)
177                 return false;
178
179         if (!xfs_verify_rtbno(mp, rtbno))
180                 return false;
181
182         if (!xfs_verify_rtbno(mp, rtbno + len - 1))
183                 return false;
184
185         if (xfs_has_rtgroups(mp) &&
186             xfs_rtb_to_rgno(mp, rtbno) != xfs_rtb_to_rgno(mp, rtbno + len - 1))
187                 return false;
188
189         return true;
190 }
191
192 /* Calculate the range of valid icount values. */
193 inline void
194 xfs_icount_range(
195         struct xfs_mount        *mp,
196         unsigned long long      *min,
197         unsigned long long      *max)
198 {
199         unsigned long long      nr_inos = 0;
200         struct xfs_perag        *pag = NULL;
201
202         /* root, rtbitmap, rtsum all live in the first chunk */
203         *min = XFS_INODES_PER_CHUNK;
204
205         while ((pag = xfs_perag_next(mp, pag)))
206                 nr_inos += pag->agino_max - pag->agino_min + 1;
207         *max = nr_inos;
208 }
209
210 /* Sanity-checking of inode counts. */
211 bool
212 xfs_verify_icount(
213         struct xfs_mount        *mp,
214         unsigned long long      icount)
215 {
216         unsigned long long      min, max;
217
218         xfs_icount_range(mp, &min, &max);
219         return icount >= min && icount <= max;
220 }
221
222 /* Sanity-checking of dir/attr block offsets. */
223 bool
224 xfs_verify_dablk(
225         struct xfs_mount        *mp,
226         xfs_fileoff_t           dabno)
227 {
228         xfs_dablk_t             max_dablk = -1U;
229
230         return dabno <= max_dablk;
231 }
232
233 /* Check that a file block offset does not exceed the maximum. */
234 bool
235 xfs_verify_fileoff(
236         struct xfs_mount        *mp,
237         xfs_fileoff_t           off)
238 {
239         return off <= XFS_MAX_FILEOFF;
240 }
241
242 /* Check that a range of file block offsets do not exceed the maximum. */
243 bool
244 xfs_verify_fileext(
245         struct xfs_mount        *mp,
246         xfs_fileoff_t           off,
247         xfs_fileoff_t           len)
248 {
249         if (off + len <= off)
250                 return false;
251
252         if (!xfs_verify_fileoff(mp, off))
253                 return false;
254
255         return xfs_verify_fileoff(mp, off + len - 1);
256 }
This page took 0.044363 seconds and 4 git commands to generate.