aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/libxfs/xfs_dir2_node.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/xfs/libxfs/xfs_dir2_node.c')
-rw-r--r--fs/xfs/libxfs/xfs_dir2_node.c51
1 files changed, 49 insertions, 2 deletions
diff --git a/fs/xfs/libxfs/xfs_dir2_node.c b/fs/xfs/libxfs/xfs_dir2_node.c
index 75a557432d0f..bbd1238852b3 100644
--- a/fs/xfs/libxfs/xfs_dir2_node.c
+++ b/fs/xfs/libxfs/xfs_dir2_node.c
@@ -155,6 +155,42 @@ const struct xfs_buf_ops xfs_dir3_free_buf_ops = {
155 .verify_write = xfs_dir3_free_write_verify, 155 .verify_write = xfs_dir3_free_write_verify,
156}; 156};
157 157
158/* Everything ok in the free block header? */
159static bool
160xfs_dir3_free_header_check(
161 struct xfs_inode *dp,
162 xfs_dablk_t fbno,
163 struct xfs_buf *bp)
164{
165 struct xfs_mount *mp = dp->i_mount;
166 unsigned int firstdb;
167 int maxbests;
168
169 maxbests = dp->d_ops->free_max_bests(mp->m_dir_geo);
170 firstdb = (xfs_dir2_da_to_db(mp->m_dir_geo, fbno) -
171 xfs_dir2_byte_to_db(mp->m_dir_geo, XFS_DIR2_FREE_OFFSET)) *
172 maxbests;
173 if (xfs_sb_version_hascrc(&mp->m_sb)) {
174 struct xfs_dir3_free_hdr *hdr3 = bp->b_addr;
175
176 if (be32_to_cpu(hdr3->firstdb) != firstdb)
177 return false;
178 if (be32_to_cpu(hdr3->nvalid) > maxbests)
179 return false;
180 if (be32_to_cpu(hdr3->nvalid) < be32_to_cpu(hdr3->nused))
181 return false;
182 } else {
183 struct xfs_dir2_free_hdr *hdr = bp->b_addr;
184
185 if (be32_to_cpu(hdr->firstdb) != firstdb)
186 return false;
187 if (be32_to_cpu(hdr->nvalid) > maxbests)
188 return false;
189 if (be32_to_cpu(hdr->nvalid) < be32_to_cpu(hdr->nused))
190 return false;
191 }
192 return true;
193}
158 194
159static int 195static int
160__xfs_dir3_free_read( 196__xfs_dir3_free_read(
@@ -168,11 +204,22 @@ __xfs_dir3_free_read(
168 204
169 err = xfs_da_read_buf(tp, dp, fbno, mappedbno, bpp, 205 err = xfs_da_read_buf(tp, dp, fbno, mappedbno, bpp,
170 XFS_DATA_FORK, &xfs_dir3_free_buf_ops); 206 XFS_DATA_FORK, &xfs_dir3_free_buf_ops);
207 if (err || !*bpp)
208 return err;
209
210 /* Check things that we can't do in the verifier. */
211 if (!xfs_dir3_free_header_check(dp, fbno, *bpp)) {
212 xfs_buf_ioerror(*bpp, -EFSCORRUPTED);
213 xfs_verifier_error(*bpp);
214 xfs_trans_brelse(tp, *bpp);
215 return -EFSCORRUPTED;
216 }
171 217
172 /* try read returns without an error or *bpp if it lands in a hole */ 218 /* try read returns without an error or *bpp if it lands in a hole */
173 if (!err && tp && *bpp) 219 if (tp)
174 xfs_trans_buf_set_type(tp, *bpp, XFS_BLFT_DIR_FREE_BUF); 220 xfs_trans_buf_set_type(tp, *bpp, XFS_BLFT_DIR_FREE_BUF);
175 return err; 221
222 return 0;
176} 223}
177 224
178int 225int