diff options
Diffstat (limited to 'fs/xfs/xfs_dir2_data.c')
-rw-r--r-- | fs/xfs/xfs_dir2_data.c | 100 |
1 files changed, 70 insertions, 30 deletions
diff --git a/fs/xfs/xfs_dir2_data.c b/fs/xfs/xfs_dir2_data.c index 8484ec4848ea..78320df3743f 100644 --- a/fs/xfs/xfs_dir2_data.c +++ b/fs/xfs/xfs_dir2_data.c | |||
@@ -31,6 +31,8 @@ | |||
31 | #include "xfs_dir2_format.h" | 31 | #include "xfs_dir2_format.h" |
32 | #include "xfs_dir2_priv.h" | 32 | #include "xfs_dir2_priv.h" |
33 | #include "xfs_error.h" | 33 | #include "xfs_error.h" |
34 | #include "xfs_buf_item.h" | ||
35 | #include "xfs_cksum.h" | ||
34 | 36 | ||
35 | STATIC xfs_dir2_data_free_t * | 37 | STATIC xfs_dir2_data_free_t * |
36 | xfs_dir2_data_freefind(xfs_dir2_data_hdr_t *hdr, xfs_dir2_data_unused_t *dup); | 38 | xfs_dir2_data_freefind(xfs_dir2_data_hdr_t *hdr, xfs_dir2_data_unused_t *dup); |
@@ -41,7 +43,7 @@ xfs_dir2_data_freefind(xfs_dir2_data_hdr_t *hdr, xfs_dir2_data_unused_t *dup); | |||
41 | * Return 0 is the buffer is good, otherwise an error. | 43 | * Return 0 is the buffer is good, otherwise an error. |
42 | */ | 44 | */ |
43 | int | 45 | int |
44 | __xfs_dir2_data_check( | 46 | __xfs_dir3_data_check( |
45 | struct xfs_inode *dp, /* incore inode pointer */ | 47 | struct xfs_inode *dp, /* incore inode pointer */ |
46 | struct xfs_buf *bp) /* data block's buffer */ | 48 | struct xfs_buf *bp) /* data block's buffer */ |
47 | { | 49 | { |
@@ -76,6 +78,7 @@ __xfs_dir2_data_check( | |||
76 | lep = xfs_dir2_block_leaf_p(btp); | 78 | lep = xfs_dir2_block_leaf_p(btp); |
77 | endp = (char *)lep; | 79 | endp = (char *)lep; |
78 | break; | 80 | break; |
81 | case cpu_to_be32(XFS_DIR3_DATA_MAGIC): | ||
79 | case cpu_to_be32(XFS_DIR2_DATA_MAGIC): | 82 | case cpu_to_be32(XFS_DIR2_DATA_MAGIC): |
80 | endp = (char *)hdr + mp->m_dirblksize; | 83 | endp = (char *)hdr + mp->m_dirblksize; |
81 | break; | 84 | break; |
@@ -189,21 +192,27 @@ __xfs_dir2_data_check( | |||
189 | return 0; | 192 | return 0; |
190 | } | 193 | } |
191 | 194 | ||
192 | static void | 195 | static bool |
193 | xfs_dir2_data_verify( | 196 | xfs_dir3_data_verify( |
194 | struct xfs_buf *bp) | 197 | struct xfs_buf *bp) |
195 | { | 198 | { |
196 | struct xfs_mount *mp = bp->b_target->bt_mount; | 199 | struct xfs_mount *mp = bp->b_target->bt_mount; |
197 | struct xfs_dir2_data_hdr *hdr = bp->b_addr; | 200 | struct xfs_dir3_blk_hdr *hdr3 = bp->b_addr; |
198 | int block_ok = 0; | ||
199 | 201 | ||
200 | block_ok = hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC); | 202 | if (xfs_sb_version_hascrc(&mp->m_sb)) { |
201 | block_ok = block_ok && __xfs_dir2_data_check(NULL, bp) == 0; | 203 | if (hdr3->magic != cpu_to_be32(XFS_DIR3_DATA_MAGIC)) |
202 | 204 | return false; | |
203 | if (!block_ok) { | 205 | if (!uuid_equal(&hdr3->uuid, &mp->m_sb.sb_uuid)) |
204 | XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, hdr); | 206 | return false; |
205 | xfs_buf_ioerror(bp, EFSCORRUPTED); | 207 | if (be64_to_cpu(hdr3->blkno) != bp->b_bn) |
208 | return false; | ||
209 | } else { | ||
210 | if (hdr3->magic != cpu_to_be32(XFS_DIR2_DATA_MAGIC)) | ||
211 | return false; | ||
206 | } | 212 | } |
213 | if (__xfs_dir3_data_check(NULL, bp)) | ||
214 | return false; | ||
215 | return true; | ||
207 | } | 216 | } |
208 | 217 | ||
209 | /* | 218 | /* |
@@ -212,7 +221,7 @@ xfs_dir2_data_verify( | |||
212 | * format buffer or a data format buffer on readahead. | 221 | * format buffer or a data format buffer on readahead. |
213 | */ | 222 | */ |
214 | static void | 223 | static void |
215 | xfs_dir2_data_reada_verify( | 224 | xfs_dir3_data_reada_verify( |
216 | struct xfs_buf *bp) | 225 | struct xfs_buf *bp) |
217 | { | 226 | { |
218 | struct xfs_mount *mp = bp->b_target->bt_mount; | 227 | struct xfs_mount *mp = bp->b_target->bt_mount; |
@@ -225,7 +234,8 @@ xfs_dir2_data_reada_verify( | |||
225 | bp->b_ops->verify_read(bp); | 234 | bp->b_ops->verify_read(bp); |
226 | return; | 235 | return; |
227 | case cpu_to_be32(XFS_DIR2_DATA_MAGIC): | 236 | case cpu_to_be32(XFS_DIR2_DATA_MAGIC): |
228 | xfs_dir2_data_verify(bp); | 237 | case cpu_to_be32(XFS_DIR3_DATA_MAGIC): |
238 | xfs_dir3_data_verify(bp); | ||
229 | return; | 239 | return; |
230 | default: | 240 | default: |
231 | XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, hdr); | 241 | XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, hdr); |
@@ -235,32 +245,56 @@ xfs_dir2_data_reada_verify( | |||
235 | } | 245 | } |
236 | 246 | ||
237 | static void | 247 | static void |
238 | xfs_dir2_data_read_verify( | 248 | xfs_dir3_data_read_verify( |
239 | struct xfs_buf *bp) | 249 | struct xfs_buf *bp) |
240 | { | 250 | { |
241 | xfs_dir2_data_verify(bp); | 251 | struct xfs_mount *mp = bp->b_target->bt_mount; |
252 | |||
253 | if ((xfs_sb_version_hascrc(&mp->m_sb) && | ||
254 | !xfs_verify_cksum(bp->b_addr, BBTOB(bp->b_length), | ||
255 | XFS_DIR3_DATA_CRC_OFF)) || | ||
256 | !xfs_dir3_data_verify(bp)) { | ||
257 | XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bp->b_addr); | ||
258 | xfs_buf_ioerror(bp, EFSCORRUPTED); | ||
259 | } | ||
242 | } | 260 | } |
243 | 261 | ||
244 | static void | 262 | static void |
245 | xfs_dir2_data_write_verify( | 263 | xfs_dir3_data_write_verify( |
246 | struct xfs_buf *bp) | 264 | struct xfs_buf *bp) |
247 | { | 265 | { |
248 | xfs_dir2_data_verify(bp); | 266 | struct xfs_mount *mp = bp->b_target->bt_mount; |
267 | struct xfs_buf_log_item *bip = bp->b_fspriv; | ||
268 | struct xfs_dir3_blk_hdr *hdr3 = bp->b_addr; | ||
269 | |||
270 | if (!xfs_dir3_data_verify(bp)) { | ||
271 | XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bp->b_addr); | ||
272 | xfs_buf_ioerror(bp, EFSCORRUPTED); | ||
273 | return; | ||
274 | } | ||
275 | |||
276 | if (!xfs_sb_version_hascrc(&mp->m_sb)) | ||
277 | return; | ||
278 | |||
279 | if (bip) | ||
280 | hdr3->lsn = cpu_to_be64(bip->bli_item.li_lsn); | ||
281 | |||
282 | xfs_update_cksum(bp->b_addr, BBTOB(bp->b_length), XFS_DIR3_DATA_CRC_OFF); | ||
249 | } | 283 | } |
250 | 284 | ||
251 | const struct xfs_buf_ops xfs_dir2_data_buf_ops = { | 285 | const struct xfs_buf_ops xfs_dir3_data_buf_ops = { |
252 | .verify_read = xfs_dir2_data_read_verify, | 286 | .verify_read = xfs_dir3_data_read_verify, |
253 | .verify_write = xfs_dir2_data_write_verify, | 287 | .verify_write = xfs_dir3_data_write_verify, |
254 | }; | 288 | }; |
255 | 289 | ||
256 | static const struct xfs_buf_ops xfs_dir2_data_reada_buf_ops = { | 290 | static const struct xfs_buf_ops xfs_dir3_data_reada_buf_ops = { |
257 | .verify_read = xfs_dir2_data_reada_verify, | 291 | .verify_read = xfs_dir3_data_reada_verify, |
258 | .verify_write = xfs_dir2_data_write_verify, | 292 | .verify_write = xfs_dir3_data_write_verify, |
259 | }; | 293 | }; |
260 | 294 | ||
261 | 295 | ||
262 | int | 296 | int |
263 | xfs_dir2_data_read( | 297 | xfs_dir3_data_read( |
264 | struct xfs_trans *tp, | 298 | struct xfs_trans *tp, |
265 | struct xfs_inode *dp, | 299 | struct xfs_inode *dp, |
266 | xfs_dablk_t bno, | 300 | xfs_dablk_t bno, |
@@ -268,18 +302,18 @@ xfs_dir2_data_read( | |||
268 | struct xfs_buf **bpp) | 302 | struct xfs_buf **bpp) |
269 | { | 303 | { |
270 | return xfs_da_read_buf(tp, dp, bno, mapped_bno, bpp, | 304 | return xfs_da_read_buf(tp, dp, bno, mapped_bno, bpp, |
271 | XFS_DATA_FORK, &xfs_dir2_data_buf_ops); | 305 | XFS_DATA_FORK, &xfs_dir3_data_buf_ops); |
272 | } | 306 | } |
273 | 307 | ||
274 | int | 308 | int |
275 | xfs_dir2_data_readahead( | 309 | xfs_dir3_data_readahead( |
276 | struct xfs_trans *tp, | 310 | struct xfs_trans *tp, |
277 | struct xfs_inode *dp, | 311 | struct xfs_inode *dp, |
278 | xfs_dablk_t bno, | 312 | xfs_dablk_t bno, |
279 | xfs_daddr_t mapped_bno) | 313 | xfs_daddr_t mapped_bno) |
280 | { | 314 | { |
281 | return xfs_da_reada_buf(tp, dp, bno, mapped_bno, | 315 | return xfs_da_reada_buf(tp, dp, bno, mapped_bno, |
282 | XFS_DATA_FORK, &xfs_dir2_data_reada_buf_ops); | 316 | XFS_DATA_FORK, &xfs_dir3_data_reada_buf_ops); |
283 | } | 317 | } |
284 | 318 | ||
285 | /* | 319 | /* |
@@ -309,6 +343,7 @@ xfs_dir2_data_freefind( | |||
309 | * one we're looking for it has to be exact. | 343 | * one we're looking for it has to be exact. |
310 | */ | 344 | */ |
311 | ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) || | 345 | ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) || |
346 | hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC) || | ||
312 | hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) || | 347 | hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) || |
313 | hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC)); | 348 | hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC)); |
314 | for (dfp = &bf[0], seenzero = matched = 0; | 349 | for (dfp = &bf[0], seenzero = matched = 0; |
@@ -458,6 +493,7 @@ xfs_dir2_data_freescan( | |||
458 | char *p; /* current entry pointer */ | 493 | char *p; /* current entry pointer */ |
459 | 494 | ||
460 | ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) || | 495 | ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) || |
496 | hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC) || | ||
461 | hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) || | 497 | hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) || |
462 | hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC)); | 498 | hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC)); |
463 | 499 | ||
@@ -534,13 +570,12 @@ xfs_dir3_data_init( | |||
534 | XFS_DATA_FORK); | 570 | XFS_DATA_FORK); |
535 | if (error) | 571 | if (error) |
536 | return error; | 572 | return error; |
537 | bp->b_ops = &xfs_dir2_data_buf_ops; | 573 | bp->b_ops = &xfs_dir3_data_buf_ops; |
538 | 574 | ||
539 | /* | 575 | /* |
540 | * Initialize the header. | 576 | * Initialize the header. |
541 | */ | 577 | */ |
542 | hdr = bp->b_addr; | 578 | hdr = bp->b_addr; |
543 | |||
544 | if (xfs_sb_version_hascrc(&mp->m_sb)) { | 579 | if (xfs_sb_version_hascrc(&mp->m_sb)) { |
545 | struct xfs_dir3_blk_hdr *hdr3 = bp->b_addr; | 580 | struct xfs_dir3_blk_hdr *hdr3 = bp->b_addr; |
546 | 581 | ||
@@ -591,6 +626,7 @@ xfs_dir2_data_log_entry( | |||
591 | xfs_dir2_data_hdr_t *hdr = bp->b_addr; | 626 | xfs_dir2_data_hdr_t *hdr = bp->b_addr; |
592 | 627 | ||
593 | ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) || | 628 | ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) || |
629 | hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC) || | ||
594 | hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) || | 630 | hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) || |
595 | hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC)); | 631 | hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC)); |
596 | 632 | ||
@@ -610,6 +646,7 @@ xfs_dir2_data_log_header( | |||
610 | xfs_dir2_data_hdr_t *hdr = bp->b_addr; | 646 | xfs_dir2_data_hdr_t *hdr = bp->b_addr; |
611 | 647 | ||
612 | ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) || | 648 | ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) || |
649 | hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC) || | ||
613 | hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) || | 650 | hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) || |
614 | hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC)); | 651 | hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC)); |
615 | 652 | ||
@@ -628,6 +665,7 @@ xfs_dir2_data_log_unused( | |||
628 | xfs_dir2_data_hdr_t *hdr = bp->b_addr; | 665 | xfs_dir2_data_hdr_t *hdr = bp->b_addr; |
629 | 666 | ||
630 | ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) || | 667 | ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) || |
668 | hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC) || | ||
631 | hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) || | 669 | hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) || |
632 | hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC)); | 670 | hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC)); |
633 | 671 | ||
@@ -675,7 +713,8 @@ xfs_dir2_data_make_free( | |||
675 | /* | 713 | /* |
676 | * Figure out where the end of the data area is. | 714 | * Figure out where the end of the data area is. |
677 | */ | 715 | */ |
678 | if (hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC)) | 716 | if (hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) || |
717 | hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC)) | ||
679 | endptr = (char *)hdr + mp->m_dirblksize; | 718 | endptr = (char *)hdr + mp->m_dirblksize; |
680 | else { | 719 | else { |
681 | xfs_dir2_block_tail_t *btp; /* block tail */ | 720 | xfs_dir2_block_tail_t *btp; /* block tail */ |
@@ -857,6 +896,7 @@ xfs_dir2_data_use_free( | |||
857 | 896 | ||
858 | hdr = bp->b_addr; | 897 | hdr = bp->b_addr; |
859 | ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) || | 898 | ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) || |
899 | hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC) || | ||
860 | hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) || | 900 | hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) || |
861 | hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC)); | 901 | hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC)); |
862 | ASSERT(be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG); | 902 | ASSERT(be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG); |