diff options
author | Dave Chinner <dchinner@redhat.com> | 2013-04-03 01:11:22 -0400 |
---|---|---|
committer | Ben Myers <bpm@sgi.com> | 2013-04-27 13:00:00 -0400 |
commit | 33363feed1614def83d0a6870051f0a7828cd61b (patch) | |
tree | 87fc721e32537e981264a1662de2c44d1d195607 | |
parent | cbc8adf89724b961c08b823d8bfb6dadbfa8733d (diff) |
xfs: add CRC checking to dir2 data blocks
This addition follows the same pattern as the dir2 block CRCs.
Signed-off-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Ben Myers <bpm@sgi.com>
Signed-off-by: Ben Myers <bpm@sgi.com>
-rw-r--r-- | fs/xfs/xfs_dir2_block.c | 22 | ||||
-rw-r--r-- | fs/xfs/xfs_dir2_data.c | 100 | ||||
-rw-r--r-- | fs/xfs/xfs_dir2_format.h | 21 | ||||
-rw-r--r-- | fs/xfs/xfs_dir2_leaf.c | 71 | ||||
-rw-r--r-- | fs/xfs/xfs_dir2_node.c | 39 | ||||
-rw-r--r-- | fs/xfs/xfs_dir2_priv.h | 12 | ||||
-rw-r--r-- | fs/xfs/xfs_file.c | 2 |
7 files changed, 162 insertions, 105 deletions
diff --git a/fs/xfs/xfs_dir2_block.c b/fs/xfs/xfs_dir2_block.c index 79a3f1b2bc7d..7ec87c20cbd2 100644 --- a/fs/xfs/xfs_dir2_block.c +++ b/fs/xfs/xfs_dir2_block.c | |||
@@ -77,7 +77,7 @@ xfs_dir3_block_verify( | |||
77 | if (hdr3->magic != cpu_to_be32(XFS_DIR2_BLOCK_MAGIC)) | 77 | if (hdr3->magic != cpu_to_be32(XFS_DIR2_BLOCK_MAGIC)) |
78 | return false; | 78 | return false; |
79 | } | 79 | } |
80 | if (__xfs_dir2_data_check(NULL, bp)) | 80 | if (__xfs_dir3_data_check(NULL, bp)) |
81 | return false; | 81 | return false; |
82 | return true; | 82 | return true; |
83 | } | 83 | } |
@@ -553,7 +553,7 @@ xfs_dir2_block_addname( | |||
553 | xfs_dir2_data_log_header(tp, bp); | 553 | xfs_dir2_data_log_header(tp, bp); |
554 | xfs_dir2_block_log_tail(tp, bp); | 554 | xfs_dir2_block_log_tail(tp, bp); |
555 | xfs_dir2_data_log_entry(tp, bp, dep); | 555 | xfs_dir2_data_log_entry(tp, bp, dep); |
556 | xfs_dir2_data_check(dp, bp); | 556 | xfs_dir3_data_check(dp, bp); |
557 | return 0; | 557 | return 0; |
558 | } | 558 | } |
559 | 559 | ||
@@ -596,7 +596,7 @@ xfs_dir2_block_getdents( | |||
596 | */ | 596 | */ |
597 | wantoff = xfs_dir2_dataptr_to_off(mp, *offset); | 597 | wantoff = xfs_dir2_dataptr_to_off(mp, *offset); |
598 | hdr = bp->b_addr; | 598 | hdr = bp->b_addr; |
599 | xfs_dir2_data_check(dp, bp); | 599 | xfs_dir3_data_check(dp, bp); |
600 | /* | 600 | /* |
601 | * Set up values for the loop. | 601 | * Set up values for the loop. |
602 | */ | 602 | */ |
@@ -720,7 +720,7 @@ xfs_dir2_block_lookup( | |||
720 | dp = args->dp; | 720 | dp = args->dp; |
721 | mp = dp->i_mount; | 721 | mp = dp->i_mount; |
722 | hdr = bp->b_addr; | 722 | hdr = bp->b_addr; |
723 | xfs_dir2_data_check(dp, bp); | 723 | xfs_dir3_data_check(dp, bp); |
724 | btp = xfs_dir2_block_tail_p(mp, hdr); | 724 | btp = xfs_dir2_block_tail_p(mp, hdr); |
725 | blp = xfs_dir2_block_leaf_p(btp); | 725 | blp = xfs_dir2_block_leaf_p(btp); |
726 | /* | 726 | /* |
@@ -771,7 +771,7 @@ xfs_dir2_block_lookup_int( | |||
771 | return error; | 771 | return error; |
772 | 772 | ||
773 | hdr = bp->b_addr; | 773 | hdr = bp->b_addr; |
774 | xfs_dir2_data_check(dp, bp); | 774 | xfs_dir3_data_check(dp, bp); |
775 | btp = xfs_dir2_block_tail_p(mp, hdr); | 775 | btp = xfs_dir2_block_tail_p(mp, hdr); |
776 | blp = xfs_dir2_block_leaf_p(btp); | 776 | blp = xfs_dir2_block_leaf_p(btp); |
777 | /* | 777 | /* |
@@ -908,7 +908,7 @@ xfs_dir2_block_removename( | |||
908 | xfs_dir2_data_freescan(mp, hdr, &needlog); | 908 | xfs_dir2_data_freescan(mp, hdr, &needlog); |
909 | if (needlog) | 909 | if (needlog) |
910 | xfs_dir2_data_log_header(tp, bp); | 910 | xfs_dir2_data_log_header(tp, bp); |
911 | xfs_dir2_data_check(dp, bp); | 911 | xfs_dir3_data_check(dp, bp); |
912 | /* | 912 | /* |
913 | * See if the size as a shortform is good enough. | 913 | * See if the size as a shortform is good enough. |
914 | */ | 914 | */ |
@@ -965,7 +965,7 @@ xfs_dir2_block_replace( | |||
965 | */ | 965 | */ |
966 | dep->inumber = cpu_to_be64(args->inumber); | 966 | dep->inumber = cpu_to_be64(args->inumber); |
967 | xfs_dir2_data_log_entry(args->trans, bp, dep); | 967 | xfs_dir2_data_log_entry(args->trans, bp, dep); |
968 | xfs_dir2_data_check(dp, bp); | 968 | xfs_dir3_data_check(dp, bp); |
969 | return 0; | 969 | return 0; |
970 | } | 970 | } |
971 | 971 | ||
@@ -1046,12 +1046,14 @@ xfs_dir2_leaf_to_block( | |||
1046 | * Read the data block if we don't already have it, give up if it fails. | 1046 | * Read the data block if we don't already have it, give up if it fails. |
1047 | */ | 1047 | */ |
1048 | if (!dbp) { | 1048 | if (!dbp) { |
1049 | error = xfs_dir2_data_read(tp, dp, mp->m_dirdatablk, -1, &dbp); | 1049 | error = xfs_dir3_data_read(tp, dp, mp->m_dirdatablk, -1, &dbp); |
1050 | if (error) | 1050 | if (error) |
1051 | return error; | 1051 | return error; |
1052 | } | 1052 | } |
1053 | hdr = dbp->b_addr; | 1053 | hdr = dbp->b_addr; |
1054 | ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC)); | 1054 | ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) || |
1055 | hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC)); | ||
1056 | |||
1055 | /* | 1057 | /* |
1056 | * Size of the "leaf" area in the block. | 1058 | * Size of the "leaf" area in the block. |
1057 | */ | 1059 | */ |
@@ -1329,6 +1331,6 @@ xfs_dir2_sf_to_block( | |||
1329 | ASSERT(needscan == 0); | 1331 | ASSERT(needscan == 0); |
1330 | xfs_dir2_block_log_leaf(tp, bp, 0, be32_to_cpu(btp->count) - 1); | 1332 | xfs_dir2_block_log_leaf(tp, bp, 0, be32_to_cpu(btp->count) - 1); |
1331 | xfs_dir2_block_log_tail(tp, bp); | 1333 | xfs_dir2_block_log_tail(tp, bp); |
1332 | xfs_dir2_data_check(dp, bp); | 1334 | xfs_dir3_data_check(dp, bp); |
1333 | return 0; | 1335 | return 0; |
1334 | } | 1336 | } |
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); |
diff --git a/fs/xfs/xfs_dir2_format.h b/fs/xfs/xfs_dir2_format.h index ec5044a92b70..0ac09502b830 100644 --- a/fs/xfs/xfs_dir2_format.h +++ b/fs/xfs/xfs_dir2_format.h | |||
@@ -283,7 +283,8 @@ struct xfs_dir3_data_hdr { | |||
283 | static inline struct xfs_dir2_data_free * | 283 | static inline struct xfs_dir2_data_free * |
284 | xfs_dir3_data_bestfree_p(struct xfs_dir2_data_hdr *hdr) | 284 | xfs_dir3_data_bestfree_p(struct xfs_dir2_data_hdr *hdr) |
285 | { | 285 | { |
286 | if (hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC)) { | 286 | if (hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC) || |
287 | hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC)) { | ||
287 | struct xfs_dir3_data_hdr *hdr3 = (struct xfs_dir3_data_hdr *)hdr; | 288 | struct xfs_dir3_data_hdr *hdr3 = (struct xfs_dir3_data_hdr *)hdr; |
288 | return hdr3->best_free; | 289 | return hdr3->best_free; |
289 | } | 290 | } |
@@ -345,17 +346,6 @@ xfs_dir2_data_unused_tag_p(struct xfs_dir2_data_unused *dup) | |||
345 | be16_to_cpu(dup->length) - sizeof(__be16)); | 346 | be16_to_cpu(dup->length) - sizeof(__be16)); |
346 | } | 347 | } |
347 | 348 | ||
348 | static inline struct xfs_dir2_data_unused * | ||
349 | xfs_dir3_data_unused_p(struct xfs_dir2_data_hdr *hdr) | ||
350 | { | ||
351 | if (hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC)) { | ||
352 | return (struct xfs_dir2_data_unused *) | ||
353 | ((char *)hdr + sizeof(struct xfs_dir3_data_hdr)); | ||
354 | } | ||
355 | return (struct xfs_dir2_data_unused *) | ||
356 | ((char *)hdr + sizeof(struct xfs_dir2_data_hdr)); | ||
357 | } | ||
358 | |||
359 | static inline size_t | 349 | static inline size_t |
360 | xfs_dir3_data_hdr_size(bool dir3) | 350 | xfs_dir3_data_hdr_size(bool dir3) |
361 | { | 351 | { |
@@ -379,6 +369,13 @@ xfs_dir3_data_entry_p(struct xfs_dir2_data_hdr *hdr) | |||
379 | ((char *)hdr + xfs_dir3_data_entry_offset(hdr)); | 369 | ((char *)hdr + xfs_dir3_data_entry_offset(hdr)); |
380 | } | 370 | } |
381 | 371 | ||
372 | static inline struct xfs_dir2_data_unused * | ||
373 | xfs_dir3_data_unused_p(struct xfs_dir2_data_hdr *hdr) | ||
374 | { | ||
375 | return (struct xfs_dir2_data_unused *) | ||
376 | ((char *)hdr + xfs_dir3_data_entry_offset(hdr)); | ||
377 | } | ||
378 | |||
382 | /* | 379 | /* |
383 | * Offsets of . and .. in data space (always block 0) | 380 | * Offsets of . and .. in data space (always block 0) |
384 | */ | 381 | */ |
diff --git a/fs/xfs/xfs_dir2_leaf.c b/fs/xfs/xfs_dir2_leaf.c index 979735b0c76d..c7dca950f768 100644 --- a/fs/xfs/xfs_dir2_leaf.c +++ b/fs/xfs/xfs_dir2_leaf.c | |||
@@ -149,7 +149,7 @@ xfs_dir2_block_to_leaf( | |||
149 | int needlog; /* need to log block header */ | 149 | int needlog; /* need to log block header */ |
150 | int needscan; /* need to rescan bestfree */ | 150 | int needscan; /* need to rescan bestfree */ |
151 | xfs_trans_t *tp; /* transaction pointer */ | 151 | xfs_trans_t *tp; /* transaction pointer */ |
152 | struct xfs_dir2_data_free *bf; | 152 | struct xfs_dir2_data_free *bf; |
153 | 153 | ||
154 | trace_xfs_dir2_block_to_leaf(args); | 154 | trace_xfs_dir2_block_to_leaf(args); |
155 | 155 | ||
@@ -175,7 +175,7 @@ xfs_dir2_block_to_leaf( | |||
175 | ASSERT(lbp != NULL); | 175 | ASSERT(lbp != NULL); |
176 | leaf = lbp->b_addr; | 176 | leaf = lbp->b_addr; |
177 | hdr = dbp->b_addr; | 177 | hdr = dbp->b_addr; |
178 | xfs_dir2_data_check(dp, dbp); | 178 | xfs_dir3_data_check(dp, dbp); |
179 | btp = xfs_dir2_block_tail_p(mp, hdr); | 179 | btp = xfs_dir2_block_tail_p(mp, hdr); |
180 | blp = xfs_dir2_block_leaf_p(btp); | 180 | blp = xfs_dir2_block_leaf_p(btp); |
181 | bf = xfs_dir3_data_bestfree_p(hdr); | 181 | bf = xfs_dir3_data_bestfree_p(hdr); |
@@ -204,8 +204,12 @@ xfs_dir2_block_to_leaf( | |||
204 | /* | 204 | /* |
205 | * Fix up the block header, make it a data block. | 205 | * Fix up the block header, make it a data block. |
206 | */ | 206 | */ |
207 | dbp->b_ops = &xfs_dir2_data_buf_ops; | 207 | dbp->b_ops = &xfs_dir3_data_buf_ops; |
208 | hdr->magic = cpu_to_be32(XFS_DIR2_DATA_MAGIC); | 208 | if (hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC)) |
209 | hdr->magic = cpu_to_be32(XFS_DIR2_DATA_MAGIC); | ||
210 | else | ||
211 | hdr->magic = cpu_to_be32(XFS_DIR3_DATA_MAGIC); | ||
212 | |||
209 | if (needscan) | 213 | if (needscan) |
210 | xfs_dir2_data_freescan(mp, hdr, &needlog); | 214 | xfs_dir2_data_freescan(mp, hdr, &needlog); |
211 | /* | 215 | /* |
@@ -221,7 +225,7 @@ xfs_dir2_block_to_leaf( | |||
221 | if (needlog) | 225 | if (needlog) |
222 | xfs_dir2_data_log_header(tp, dbp); | 226 | xfs_dir2_data_log_header(tp, dbp); |
223 | xfs_dir2_leaf_check(dp, lbp); | 227 | xfs_dir2_leaf_check(dp, lbp); |
224 | xfs_dir2_data_check(dp, dbp); | 228 | xfs_dir3_data_check(dp, dbp); |
225 | xfs_dir2_leaf_log_bests(tp, lbp, 0, 0); | 229 | xfs_dir2_leaf_log_bests(tp, lbp, 0, 0); |
226 | return 0; | 230 | return 0; |
227 | } | 231 | } |
@@ -385,6 +389,7 @@ xfs_dir2_leaf_addname( | |||
385 | __be16 *tagp; /* end of data entry */ | 389 | __be16 *tagp; /* end of data entry */ |
386 | xfs_trans_t *tp; /* transaction pointer */ | 390 | xfs_trans_t *tp; /* transaction pointer */ |
387 | xfs_dir2_db_t use_block; /* data block number */ | 391 | xfs_dir2_db_t use_block; /* data block number */ |
392 | struct xfs_dir2_data_free *bf; /* bestfree table */ | ||
388 | 393 | ||
389 | trace_xfs_dir2_leaf_addname(args); | 394 | trace_xfs_dir2_leaf_addname(args); |
390 | 395 | ||
@@ -568,14 +573,15 @@ xfs_dir2_leaf_addname( | |||
568 | else | 573 | else |
569 | xfs_dir2_leaf_log_bests(tp, lbp, use_block, use_block); | 574 | xfs_dir2_leaf_log_bests(tp, lbp, use_block, use_block); |
570 | hdr = dbp->b_addr; | 575 | hdr = dbp->b_addr; |
571 | bestsp[use_block] = hdr->bestfree[0].length; | 576 | bf = xfs_dir3_data_bestfree_p(hdr); |
577 | bestsp[use_block] = bf[0].length; | ||
572 | grown = 1; | 578 | grown = 1; |
573 | } else { | 579 | } else { |
574 | /* | 580 | /* |
575 | * Already had space in some data block. | 581 | * Already had space in some data block. |
576 | * Just read that one in. | 582 | * Just read that one in. |
577 | */ | 583 | */ |
578 | error = xfs_dir2_data_read(tp, dp, | 584 | error = xfs_dir3_data_read(tp, dp, |
579 | xfs_dir2_db_to_da(mp, use_block), | 585 | xfs_dir2_db_to_da(mp, use_block), |
580 | -1, &dbp); | 586 | -1, &dbp); |
581 | if (error) { | 587 | if (error) { |
@@ -583,13 +589,14 @@ xfs_dir2_leaf_addname( | |||
583 | return error; | 589 | return error; |
584 | } | 590 | } |
585 | hdr = dbp->b_addr; | 591 | hdr = dbp->b_addr; |
592 | bf = xfs_dir3_data_bestfree_p(hdr); | ||
586 | grown = 0; | 593 | grown = 0; |
587 | } | 594 | } |
588 | /* | 595 | /* |
589 | * Point to the biggest freespace in our data block. | 596 | * Point to the biggest freespace in our data block. |
590 | */ | 597 | */ |
591 | dup = (xfs_dir2_data_unused_t *) | 598 | dup = (xfs_dir2_data_unused_t *) |
592 | ((char *)hdr + be16_to_cpu(hdr->bestfree[0].offset)); | 599 | ((char *)hdr + be16_to_cpu(bf[0].offset)); |
593 | ASSERT(be16_to_cpu(dup->length) >= length); | 600 | ASSERT(be16_to_cpu(dup->length) >= length); |
594 | needscan = needlog = 0; | 601 | needscan = needlog = 0; |
595 | /* | 602 | /* |
@@ -622,8 +629,8 @@ xfs_dir2_leaf_addname( | |||
622 | * If the bests table needs to be changed, do it. | 629 | * If the bests table needs to be changed, do it. |
623 | * Log the change unless we've already done that. | 630 | * Log the change unless we've already done that. |
624 | */ | 631 | */ |
625 | if (be16_to_cpu(bestsp[use_block]) != be16_to_cpu(hdr->bestfree[0].length)) { | 632 | if (be16_to_cpu(bestsp[use_block]) != be16_to_cpu(bf[0].length)) { |
626 | bestsp[use_block] = hdr->bestfree[0].length; | 633 | bestsp[use_block] = bf[0].length; |
627 | if (!grown) | 634 | if (!grown) |
628 | xfs_dir2_leaf_log_bests(tp, lbp, use_block, use_block); | 635 | xfs_dir2_leaf_log_bests(tp, lbp, use_block, use_block); |
629 | } | 636 | } |
@@ -643,7 +650,7 @@ xfs_dir2_leaf_addname( | |||
643 | xfs_dir2_leaf_log_header(tp, lbp); | 650 | xfs_dir2_leaf_log_header(tp, lbp); |
644 | xfs_dir2_leaf_log_ents(tp, lbp, lfloglow, lfloghigh); | 651 | xfs_dir2_leaf_log_ents(tp, lbp, lfloglow, lfloghigh); |
645 | xfs_dir2_leaf_check(dp, lbp); | 652 | xfs_dir2_leaf_check(dp, lbp); |
646 | xfs_dir2_data_check(dp, dbp); | 653 | xfs_dir3_data_check(dp, dbp); |
647 | return 0; | 654 | return 0; |
648 | } | 655 | } |
649 | 656 | ||
@@ -967,7 +974,7 @@ xfs_dir2_leaf_readbuf( | |||
967 | * Read the directory block starting at the first mapping. | 974 | * Read the directory block starting at the first mapping. |
968 | */ | 975 | */ |
969 | mip->curdb = xfs_dir2_da_to_db(mp, map->br_startoff); | 976 | mip->curdb = xfs_dir2_da_to_db(mp, map->br_startoff); |
970 | error = xfs_dir2_data_read(NULL, dp, map->br_startoff, | 977 | error = xfs_dir3_data_read(NULL, dp, map->br_startoff, |
971 | map->br_blockcount >= mp->m_dirblkfsbs ? | 978 | map->br_blockcount >= mp->m_dirblkfsbs ? |
972 | XFS_FSB_TO_DADDR(mp, map->br_startblock) : -1, &bp); | 979 | XFS_FSB_TO_DADDR(mp, map->br_startblock) : -1, &bp); |
973 | 980 | ||
@@ -996,7 +1003,7 @@ xfs_dir2_leaf_readbuf( | |||
996 | */ | 1003 | */ |
997 | if (i > mip->ra_current && | 1004 | if (i > mip->ra_current && |
998 | map[mip->ra_index].br_blockcount >= mp->m_dirblkfsbs) { | 1005 | map[mip->ra_index].br_blockcount >= mp->m_dirblkfsbs) { |
999 | xfs_dir2_data_readahead(NULL, dp, | 1006 | xfs_dir3_data_readahead(NULL, dp, |
1000 | map[mip->ra_index].br_startoff + mip->ra_offset, | 1007 | map[mip->ra_index].br_startoff + mip->ra_offset, |
1001 | XFS_FSB_TO_DADDR(mp, | 1008 | XFS_FSB_TO_DADDR(mp, |
1002 | map[mip->ra_index].br_startblock + | 1009 | map[mip->ra_index].br_startblock + |
@@ -1009,7 +1016,7 @@ xfs_dir2_leaf_readbuf( | |||
1009 | * use our mapping, but this is a very rare case. | 1016 | * use our mapping, but this is a very rare case. |
1010 | */ | 1017 | */ |
1011 | else if (i > mip->ra_current) { | 1018 | else if (i > mip->ra_current) { |
1012 | xfs_dir2_data_readahead(NULL, dp, | 1019 | xfs_dir3_data_readahead(NULL, dp, |
1013 | map[mip->ra_index].br_startoff + | 1020 | map[mip->ra_index].br_startoff + |
1014 | mip->ra_offset, -1); | 1021 | mip->ra_offset, -1); |
1015 | mip->ra_current = i; | 1022 | mip->ra_current = i; |
@@ -1135,17 +1142,17 @@ xfs_dir2_leaf_getdents( | |||
1135 | ASSERT(xfs_dir2_byte_to_db(mp, curoff) == | 1142 | ASSERT(xfs_dir2_byte_to_db(mp, curoff) == |
1136 | map_info->curdb); | 1143 | map_info->curdb); |
1137 | hdr = bp->b_addr; | 1144 | hdr = bp->b_addr; |
1138 | xfs_dir2_data_check(dp, bp); | 1145 | xfs_dir3_data_check(dp, bp); |
1139 | /* | 1146 | /* |
1140 | * Find our position in the block. | 1147 | * Find our position in the block. |
1141 | */ | 1148 | */ |
1142 | ptr = (char *)(hdr + 1); | 1149 | ptr = (char *)xfs_dir3_data_entry_p(hdr); |
1143 | byteoff = xfs_dir2_byte_to_off(mp, curoff); | 1150 | byteoff = xfs_dir2_byte_to_off(mp, curoff); |
1144 | /* | 1151 | /* |
1145 | * Skip past the header. | 1152 | * Skip past the header. |
1146 | */ | 1153 | */ |
1147 | if (byteoff == 0) | 1154 | if (byteoff == 0) |
1148 | curoff += (uint)sizeof(*hdr); | 1155 | curoff += xfs_dir3_data_entry_offset(hdr); |
1149 | /* | 1156 | /* |
1150 | * Skip past entries until we reach our offset. | 1157 | * Skip past entries until we reach our offset. |
1151 | */ | 1158 | */ |
@@ -1481,7 +1488,7 @@ xfs_dir2_leaf_lookup_int( | |||
1481 | if (newdb != curdb) { | 1488 | if (newdb != curdb) { |
1482 | if (dbp) | 1489 | if (dbp) |
1483 | xfs_trans_brelse(tp, dbp); | 1490 | xfs_trans_brelse(tp, dbp); |
1484 | error = xfs_dir2_data_read(tp, dp, | 1491 | error = xfs_dir3_data_read(tp, dp, |
1485 | xfs_dir2_db_to_da(mp, newdb), | 1492 | xfs_dir2_db_to_da(mp, newdb), |
1486 | -1, &dbp); | 1493 | -1, &dbp); |
1487 | if (error) { | 1494 | if (error) { |
@@ -1522,7 +1529,7 @@ xfs_dir2_leaf_lookup_int( | |||
1522 | ASSERT(cidb != -1); | 1529 | ASSERT(cidb != -1); |
1523 | if (cidb != curdb) { | 1530 | if (cidb != curdb) { |
1524 | xfs_trans_brelse(tp, dbp); | 1531 | xfs_trans_brelse(tp, dbp); |
1525 | error = xfs_dir2_data_read(tp, dp, | 1532 | error = xfs_dir3_data_read(tp, dp, |
1526 | xfs_dir2_db_to_da(mp, cidb), | 1533 | xfs_dir2_db_to_da(mp, cidb), |
1527 | -1, &dbp); | 1534 | -1, &dbp); |
1528 | if (error) { | 1535 | if (error) { |
@@ -1568,6 +1575,7 @@ xfs_dir2_leaf_removename( | |||
1568 | int needscan; /* need to rescan data frees */ | 1575 | int needscan; /* need to rescan data frees */ |
1569 | xfs_dir2_data_off_t oldbest; /* old value of best free */ | 1576 | xfs_dir2_data_off_t oldbest; /* old value of best free */ |
1570 | xfs_trans_t *tp; /* transaction pointer */ | 1577 | xfs_trans_t *tp; /* transaction pointer */ |
1578 | struct xfs_dir2_data_free *bf; /* bestfree table */ | ||
1571 | 1579 | ||
1572 | trace_xfs_dir2_leaf_removename(args); | 1580 | trace_xfs_dir2_leaf_removename(args); |
1573 | 1581 | ||
@@ -1582,7 +1590,8 @@ xfs_dir2_leaf_removename( | |||
1582 | mp = dp->i_mount; | 1590 | mp = dp->i_mount; |
1583 | leaf = lbp->b_addr; | 1591 | leaf = lbp->b_addr; |
1584 | hdr = dbp->b_addr; | 1592 | hdr = dbp->b_addr; |
1585 | xfs_dir2_data_check(dp, dbp); | 1593 | bf = xfs_dir3_data_bestfree_p(hdr); |
1594 | xfs_dir3_data_check(dp, dbp); | ||
1586 | /* | 1595 | /* |
1587 | * Point to the leaf entry, use that to point to the data entry. | 1596 | * Point to the leaf entry, use that to point to the data entry. |
1588 | */ | 1597 | */ |
@@ -1591,7 +1600,7 @@ xfs_dir2_leaf_removename( | |||
1591 | dep = (xfs_dir2_data_entry_t *) | 1600 | dep = (xfs_dir2_data_entry_t *) |
1592 | ((char *)hdr + xfs_dir2_dataptr_to_off(mp, be32_to_cpu(lep->address))); | 1601 | ((char *)hdr + xfs_dir2_dataptr_to_off(mp, be32_to_cpu(lep->address))); |
1593 | needscan = needlog = 0; | 1602 | needscan = needlog = 0; |
1594 | oldbest = be16_to_cpu(hdr->bestfree[0].length); | 1603 | oldbest = be16_to_cpu(bf[0].length); |
1595 | ltp = xfs_dir2_leaf_tail_p(mp, leaf); | 1604 | ltp = xfs_dir2_leaf_tail_p(mp, leaf); |
1596 | bestsp = xfs_dir2_leaf_bests_p(ltp); | 1605 | bestsp = xfs_dir2_leaf_bests_p(ltp); |
1597 | ASSERT(be16_to_cpu(bestsp[db]) == oldbest); | 1606 | ASSERT(be16_to_cpu(bestsp[db]) == oldbest); |
@@ -1620,16 +1629,16 @@ xfs_dir2_leaf_removename( | |||
1620 | * If the longest freespace in the data block has changed, | 1629 | * If the longest freespace in the data block has changed, |
1621 | * put the new value in the bests table and log that. | 1630 | * put the new value in the bests table and log that. |
1622 | */ | 1631 | */ |
1623 | if (be16_to_cpu(hdr->bestfree[0].length) != oldbest) { | 1632 | if (be16_to_cpu(bf[0].length) != oldbest) { |
1624 | bestsp[db] = hdr->bestfree[0].length; | 1633 | bestsp[db] = bf[0].length; |
1625 | xfs_dir2_leaf_log_bests(tp, lbp, db, db); | 1634 | xfs_dir2_leaf_log_bests(tp, lbp, db, db); |
1626 | } | 1635 | } |
1627 | xfs_dir2_data_check(dp, dbp); | 1636 | xfs_dir3_data_check(dp, dbp); |
1628 | /* | 1637 | /* |
1629 | * If the data block is now empty then get rid of the data block. | 1638 | * If the data block is now empty then get rid of the data block. |
1630 | */ | 1639 | */ |
1631 | if (be16_to_cpu(hdr->bestfree[0].length) == | 1640 | if (be16_to_cpu(bf[0].length) == |
1632 | mp->m_dirblksize - (uint)sizeof(*hdr)) { | 1641 | mp->m_dirblksize - xfs_dir3_data_entry_offset(hdr)) { |
1633 | ASSERT(db != mp->m_dirdatablk); | 1642 | ASSERT(db != mp->m_dirdatablk); |
1634 | if ((error = xfs_dir2_shrink_inode(args, db, dbp))) { | 1643 | if ((error = xfs_dir2_shrink_inode(args, db, dbp))) { |
1635 | /* | 1644 | /* |
@@ -1809,7 +1818,7 @@ xfs_dir2_leaf_trim_data( | |||
1809 | /* | 1818 | /* |
1810 | * Read the offending data block. We need its buffer. | 1819 | * Read the offending data block. We need its buffer. |
1811 | */ | 1820 | */ |
1812 | error = xfs_dir2_data_read(tp, dp, xfs_dir2_db_to_da(mp, db), -1, &dbp); | 1821 | error = xfs_dir3_data_read(tp, dp, xfs_dir2_db_to_da(mp, db), -1, &dbp); |
1813 | if (error) | 1822 | if (error) |
1814 | return error; | 1823 | return error; |
1815 | 1824 | ||
@@ -1819,10 +1828,12 @@ xfs_dir2_leaf_trim_data( | |||
1819 | #ifdef DEBUG | 1828 | #ifdef DEBUG |
1820 | { | 1829 | { |
1821 | struct xfs_dir2_data_hdr *hdr = dbp->b_addr; | 1830 | struct xfs_dir2_data_hdr *hdr = dbp->b_addr; |
1831 | struct xfs_dir2_data_free *bf = xfs_dir3_data_bestfree_p(hdr); | ||
1822 | 1832 | ||
1823 | ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC)); | 1833 | ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) || |
1824 | ASSERT(be16_to_cpu(hdr->bestfree[0].length) == | 1834 | hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC)); |
1825 | mp->m_dirblksize - (uint)sizeof(*hdr)); | 1835 | ASSERT(be16_to_cpu(bf[0].length) == |
1836 | mp->m_dirblksize - xfs_dir3_data_entry_offset(hdr)); | ||
1826 | ASSERT(db == be32_to_cpu(ltp->bestcount) - 1); | 1837 | ASSERT(db == be32_to_cpu(ltp->bestcount) - 1); |
1827 | } | 1838 | } |
1828 | #endif | 1839 | #endif |
diff --git a/fs/xfs/xfs_dir2_node.c b/fs/xfs/xfs_dir2_node.c index 0fe39b9fde7e..abf617d5060b 100644 --- a/fs/xfs/xfs_dir2_node.c +++ b/fs/xfs/xfs_dir2_node.c | |||
@@ -753,13 +753,13 @@ xfs_dir2_leafn_lookup_for_entry( | |||
753 | ASSERT(state->extravalid); | 753 | ASSERT(state->extravalid); |
754 | curbp = state->extrablk.bp; | 754 | curbp = state->extrablk.bp; |
755 | } else { | 755 | } else { |
756 | error = xfs_dir2_data_read(tp, dp, | 756 | error = xfs_dir3_data_read(tp, dp, |
757 | xfs_dir2_db_to_da(mp, newdb), | 757 | xfs_dir2_db_to_da(mp, newdb), |
758 | -1, &curbp); | 758 | -1, &curbp); |
759 | if (error) | 759 | if (error) |
760 | return error; | 760 | return error; |
761 | } | 761 | } |
762 | xfs_dir2_data_check(dp, curbp); | 762 | xfs_dir3_data_check(dp, curbp); |
763 | curdb = newdb; | 763 | curdb = newdb; |
764 | } | 764 | } |
765 | /* | 765 | /* |
@@ -787,7 +787,7 @@ xfs_dir2_leafn_lookup_for_entry( | |||
787 | state->extrablk.index = (int)((char *)dep - | 787 | state->extrablk.index = (int)((char *)dep - |
788 | (char *)curbp->b_addr); | 788 | (char *)curbp->b_addr); |
789 | state->extrablk.magic = XFS_DIR2_DATA_MAGIC; | 789 | state->extrablk.magic = XFS_DIR2_DATA_MAGIC; |
790 | curbp->b_ops = &xfs_dir2_data_buf_ops; | 790 | curbp->b_ops = &xfs_dir3_data_buf_ops; |
791 | if (cmp == XFS_CMP_EXACT) | 791 | if (cmp == XFS_CMP_EXACT) |
792 | return XFS_ERROR(EEXIST); | 792 | return XFS_ERROR(EEXIST); |
793 | } | 793 | } |
@@ -802,7 +802,7 @@ xfs_dir2_leafn_lookup_for_entry( | |||
802 | state->extrablk.index = -1; | 802 | state->extrablk.index = -1; |
803 | state->extrablk.blkno = curdb; | 803 | state->extrablk.blkno = curdb; |
804 | state->extrablk.magic = XFS_DIR2_DATA_MAGIC; | 804 | state->extrablk.magic = XFS_DIR2_DATA_MAGIC; |
805 | curbp->b_ops = &xfs_dir2_data_buf_ops; | 805 | curbp->b_ops = &xfs_dir3_data_buf_ops; |
806 | } else { | 806 | } else { |
807 | /* If the curbp is not the CI match block, drop it */ | 807 | /* If the curbp is not the CI match block, drop it */ |
808 | if (state->extrablk.bp != curbp) | 808 | if (state->extrablk.bp != curbp) |
@@ -1152,6 +1152,7 @@ xfs_dir2_leafn_remove( | |||
1152 | int needlog; /* need to log data header */ | 1152 | int needlog; /* need to log data header */ |
1153 | int needscan; /* need to rescan data frees */ | 1153 | int needscan; /* need to rescan data frees */ |
1154 | xfs_trans_t *tp; /* transaction pointer */ | 1154 | xfs_trans_t *tp; /* transaction pointer */ |
1155 | struct xfs_dir2_data_free *bf; /* bestfree table */ | ||
1155 | 1156 | ||
1156 | trace_xfs_dir2_leafn_remove(args, index); | 1157 | trace_xfs_dir2_leafn_remove(args, index); |
1157 | 1158 | ||
@@ -1186,7 +1187,8 @@ xfs_dir2_leafn_remove( | |||
1186 | dbp = dblk->bp; | 1187 | dbp = dblk->bp; |
1187 | hdr = dbp->b_addr; | 1188 | hdr = dbp->b_addr; |
1188 | dep = (xfs_dir2_data_entry_t *)((char *)hdr + off); | 1189 | dep = (xfs_dir2_data_entry_t *)((char *)hdr + off); |
1189 | longest = be16_to_cpu(hdr->bestfree[0].length); | 1190 | bf = xfs_dir3_data_bestfree_p(hdr); |
1191 | longest = be16_to_cpu(bf[0].length); | ||
1190 | needlog = needscan = 0; | 1192 | needlog = needscan = 0; |
1191 | xfs_dir2_data_make_free(tp, dbp, off, | 1193 | xfs_dir2_data_make_free(tp, dbp, off, |
1192 | xfs_dir2_data_entsize(dep->namelen), &needlog, &needscan); | 1194 | xfs_dir2_data_entsize(dep->namelen), &needlog, &needscan); |
@@ -1198,12 +1200,12 @@ xfs_dir2_leafn_remove( | |||
1198 | xfs_dir2_data_freescan(mp, hdr, &needlog); | 1200 | xfs_dir2_data_freescan(mp, hdr, &needlog); |
1199 | if (needlog) | 1201 | if (needlog) |
1200 | xfs_dir2_data_log_header(tp, dbp); | 1202 | xfs_dir2_data_log_header(tp, dbp); |
1201 | xfs_dir2_data_check(dp, dbp); | 1203 | xfs_dir3_data_check(dp, dbp); |
1202 | /* | 1204 | /* |
1203 | * If the longest data block freespace changes, need to update | 1205 | * If the longest data block freespace changes, need to update |
1204 | * the corresponding freeblock entry. | 1206 | * the corresponding freeblock entry. |
1205 | */ | 1207 | */ |
1206 | if (longest < be16_to_cpu(hdr->bestfree[0].length)) { | 1208 | if (longest < be16_to_cpu(bf[0].length)) { |
1207 | int error; /* error return value */ | 1209 | int error; /* error return value */ |
1208 | struct xfs_buf *fbp; /* freeblock buffer */ | 1210 | struct xfs_buf *fbp; /* freeblock buffer */ |
1209 | xfs_dir2_db_t fdb; /* freeblock block number */ | 1211 | xfs_dir2_db_t fdb; /* freeblock block number */ |
@@ -1232,12 +1234,13 @@ xfs_dir2_leafn_remove( | |||
1232 | * Calculate which entry we need to fix. | 1234 | * Calculate which entry we need to fix. |
1233 | */ | 1235 | */ |
1234 | findex = xfs_dir2_db_to_fdindex(mp, db); | 1236 | findex = xfs_dir2_db_to_fdindex(mp, db); |
1235 | longest = be16_to_cpu(hdr->bestfree[0].length); | 1237 | longest = be16_to_cpu(bf[0].length); |
1236 | /* | 1238 | /* |
1237 | * If the data block is now empty we can get rid of it | 1239 | * If the data block is now empty we can get rid of it |
1238 | * (usually). | 1240 | * (usually). |
1239 | */ | 1241 | */ |
1240 | if (longest == mp->m_dirblksize - (uint)sizeof(*hdr)) { | 1242 | if (longest == mp->m_dirblksize - |
1243 | xfs_dir3_data_entry_offset(hdr)) { | ||
1241 | /* | 1244 | /* |
1242 | * Try to punch out the data block. | 1245 | * Try to punch out the data block. |
1243 | */ | 1246 | */ |
@@ -1611,6 +1614,7 @@ xfs_dir2_node_addname_int( | |||
1611 | xfs_trans_t *tp; /* transaction pointer */ | 1614 | xfs_trans_t *tp; /* transaction pointer */ |
1612 | __be16 *bests; | 1615 | __be16 *bests; |
1613 | struct xfs_dir3_icfree_hdr freehdr; | 1616 | struct xfs_dir3_icfree_hdr freehdr; |
1617 | struct xfs_dir2_data_free *bf; | ||
1614 | 1618 | ||
1615 | dp = args->dp; | 1619 | dp = args->dp; |
1616 | mp = dp->i_mount; | 1620 | mp = dp->i_mount; |
@@ -1868,7 +1872,8 @@ xfs_dir2_node_addname_int( | |||
1868 | * change again. | 1872 | * change again. |
1869 | */ | 1873 | */ |
1870 | hdr = dbp->b_addr; | 1874 | hdr = dbp->b_addr; |
1871 | bests[findex] = hdr->bestfree[0].length; | 1875 | bf = xfs_dir3_data_bestfree_p(hdr); |
1876 | bests[findex] = bf[0].length; | ||
1872 | logfree = 1; | 1877 | logfree = 1; |
1873 | } | 1878 | } |
1874 | /* | 1879 | /* |
@@ -1884,19 +1889,20 @@ xfs_dir2_node_addname_int( | |||
1884 | /* | 1889 | /* |
1885 | * Read the data block in. | 1890 | * Read the data block in. |
1886 | */ | 1891 | */ |
1887 | error = xfs_dir2_data_read(tp, dp, xfs_dir2_db_to_da(mp, dbno), | 1892 | error = xfs_dir3_data_read(tp, dp, xfs_dir2_db_to_da(mp, dbno), |
1888 | -1, &dbp); | 1893 | -1, &dbp); |
1889 | if (error) | 1894 | if (error) |
1890 | return error; | 1895 | return error; |
1891 | hdr = dbp->b_addr; | 1896 | hdr = dbp->b_addr; |
1897 | bf = xfs_dir3_data_bestfree_p(hdr); | ||
1892 | logfree = 0; | 1898 | logfree = 0; |
1893 | } | 1899 | } |
1894 | ASSERT(be16_to_cpu(hdr->bestfree[0].length) >= length); | 1900 | ASSERT(be16_to_cpu(bf[0].length) >= length); |
1895 | /* | 1901 | /* |
1896 | * Point to the existing unused space. | 1902 | * Point to the existing unused space. |
1897 | */ | 1903 | */ |
1898 | dup = (xfs_dir2_data_unused_t *) | 1904 | dup = (xfs_dir2_data_unused_t *) |
1899 | ((char *)hdr + be16_to_cpu(hdr->bestfree[0].offset)); | 1905 | ((char *)hdr + be16_to_cpu(bf[0].offset)); |
1900 | needscan = needlog = 0; | 1906 | needscan = needlog = 0; |
1901 | /* | 1907 | /* |
1902 | * Mark the first part of the unused space, inuse for us. | 1908 | * Mark the first part of the unused space, inuse for us. |
@@ -1928,8 +1934,8 @@ xfs_dir2_node_addname_int( | |||
1928 | * If the freespace entry is now wrong, update it. | 1934 | * If the freespace entry is now wrong, update it. |
1929 | */ | 1935 | */ |
1930 | bests = xfs_dir3_free_bests_p(mp, free); /* gcc is so stupid */ | 1936 | bests = xfs_dir3_free_bests_p(mp, free); /* gcc is so stupid */ |
1931 | if (be16_to_cpu(bests[findex]) != be16_to_cpu(hdr->bestfree[0].length)) { | 1937 | if (be16_to_cpu(bests[findex]) != be16_to_cpu(bf[0].length)) { |
1932 | bests[findex] = hdr->bestfree[0].length; | 1938 | bests[findex] = bf[0].length; |
1933 | logfree = 1; | 1939 | logfree = 1; |
1934 | } | 1940 | } |
1935 | /* | 1941 | /* |
@@ -2119,7 +2125,8 @@ xfs_dir2_node_replace( | |||
2119 | * Point to the data entry. | 2125 | * Point to the data entry. |
2120 | */ | 2126 | */ |
2121 | hdr = state->extrablk.bp->b_addr; | 2127 | hdr = state->extrablk.bp->b_addr; |
2122 | ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC)); | 2128 | ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) || |
2129 | hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC)); | ||
2123 | dep = (xfs_dir2_data_entry_t *) | 2130 | dep = (xfs_dir2_data_entry_t *) |
2124 | ((char *)hdr + | 2131 | ((char *)hdr + |
2125 | xfs_dir2_dataptr_to_off(state->mp, be32_to_cpu(lep->address))); | 2132 | xfs_dir2_dataptr_to_off(state->mp, be32_to_cpu(lep->address))); |
diff --git a/fs/xfs/xfs_dir2_priv.h b/fs/xfs/xfs_dir2_priv.h index e6f2e0a7bb65..910e64413316 100644 --- a/fs/xfs/xfs_dir2_priv.h +++ b/fs/xfs/xfs_dir2_priv.h | |||
@@ -43,17 +43,17 @@ extern int xfs_dir2_leaf_to_block(struct xfs_da_args *args, | |||
43 | 43 | ||
44 | /* xfs_dir2_data.c */ | 44 | /* xfs_dir2_data.c */ |
45 | #ifdef DEBUG | 45 | #ifdef DEBUG |
46 | #define xfs_dir2_data_check(dp,bp) __xfs_dir2_data_check(dp, bp); | 46 | #define xfs_dir3_data_check(dp,bp) __xfs_dir3_data_check(dp, bp); |
47 | #else | 47 | #else |
48 | #define xfs_dir2_data_check(dp,bp) | 48 | #define xfs_dir3_data_check(dp,bp) |
49 | #endif | 49 | #endif |
50 | 50 | ||
51 | extern const struct xfs_buf_ops xfs_dir2_data_buf_ops; | 51 | extern const struct xfs_buf_ops xfs_dir3_data_buf_ops; |
52 | 52 | ||
53 | extern int __xfs_dir2_data_check(struct xfs_inode *dp, struct xfs_buf *bp); | 53 | extern int __xfs_dir3_data_check(struct xfs_inode *dp, struct xfs_buf *bp); |
54 | extern int xfs_dir2_data_read(struct xfs_trans *tp, struct xfs_inode *dp, | 54 | extern int xfs_dir3_data_read(struct xfs_trans *tp, struct xfs_inode *dp, |
55 | xfs_dablk_t bno, xfs_daddr_t mapped_bno, struct xfs_buf **bpp); | 55 | xfs_dablk_t bno, xfs_daddr_t mapped_bno, struct xfs_buf **bpp); |
56 | extern int xfs_dir2_data_readahead(struct xfs_trans *tp, struct xfs_inode *dp, | 56 | extern int xfs_dir3_data_readahead(struct xfs_trans *tp, struct xfs_inode *dp, |
57 | xfs_dablk_t bno, xfs_daddr_t mapped_bno); | 57 | xfs_dablk_t bno, xfs_daddr_t mapped_bno); |
58 | 58 | ||
59 | extern struct xfs_dir2_data_free * | 59 | extern struct xfs_dir2_data_free * |
diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c index f03bf1a456fb..cf6eacd4169a 100644 --- a/fs/xfs/xfs_file.c +++ b/fs/xfs/xfs_file.c | |||
@@ -893,7 +893,7 @@ xfs_dir_open( | |||
893 | */ | 893 | */ |
894 | mode = xfs_ilock_map_shared(ip); | 894 | mode = xfs_ilock_map_shared(ip); |
895 | if (ip->i_d.di_nextents > 0) | 895 | if (ip->i_d.di_nextents > 0) |
896 | xfs_dir2_data_readahead(NULL, ip, 0, -1); | 896 | xfs_dir3_data_readahead(NULL, ip, 0, -1); |
897 | xfs_iunlock(ip, mode); | 897 | xfs_iunlock(ip, mode); |
898 | return 0; | 898 | return 0; |
899 | } | 899 | } |