diff options
Diffstat (limited to 'fs/xfs/xfs_buf_item.c')
| -rw-r--r-- | fs/xfs/xfs_buf_item.c | 67 |
1 files changed, 51 insertions, 16 deletions
diff --git a/fs/xfs/xfs_buf_item.c b/fs/xfs/xfs_buf_item.c index a8d0ed911196..77b09750e92c 100644 --- a/fs/xfs/xfs_buf_item.c +++ b/fs/xfs/xfs_buf_item.c | |||
| @@ -71,7 +71,7 @@ xfs_buf_item_log_debug( | |||
| 71 | chunk_num = byte >> XFS_BLF_SHIFT; | 71 | chunk_num = byte >> XFS_BLF_SHIFT; |
| 72 | word_num = chunk_num >> BIT_TO_WORD_SHIFT; | 72 | word_num = chunk_num >> BIT_TO_WORD_SHIFT; |
| 73 | bit_num = chunk_num & (NBWORD - 1); | 73 | bit_num = chunk_num & (NBWORD - 1); |
| 74 | wordp = &(bip->bli_format.blf_data_map[word_num]); | 74 | wordp = &(bip->__bli_format.blf_data_map[word_num]); |
| 75 | bit_set = *wordp & (1 << bit_num); | 75 | bit_set = *wordp & (1 << bit_num); |
| 76 | ASSERT(bit_set); | 76 | ASSERT(bit_set); |
| 77 | byte++; | 77 | byte++; |
| @@ -237,7 +237,7 @@ xfs_buf_item_size( | |||
| 237 | * cancel flag in it. | 237 | * cancel flag in it. |
| 238 | */ | 238 | */ |
| 239 | trace_xfs_buf_item_size_stale(bip); | 239 | trace_xfs_buf_item_size_stale(bip); |
| 240 | ASSERT(bip->bli_format.blf_flags & XFS_BLF_CANCEL); | 240 | ASSERT(bip->__bli_format.blf_flags & XFS_BLF_CANCEL); |
| 241 | return bip->bli_format_count; | 241 | return bip->bli_format_count; |
| 242 | } | 242 | } |
| 243 | 243 | ||
| @@ -278,7 +278,7 @@ xfs_buf_item_format_segment( | |||
| 278 | uint buffer_offset; | 278 | uint buffer_offset; |
| 279 | 279 | ||
| 280 | /* copy the flags across from the base format item */ | 280 | /* copy the flags across from the base format item */ |
| 281 | blfp->blf_flags = bip->bli_format.blf_flags; | 281 | blfp->blf_flags = bip->__bli_format.blf_flags; |
| 282 | 282 | ||
| 283 | /* | 283 | /* |
| 284 | * Base size is the actual size of the ondisk structure - it reflects | 284 | * Base size is the actual size of the ondisk structure - it reflects |
| @@ -287,6 +287,17 @@ xfs_buf_item_format_segment( | |||
| 287 | */ | 287 | */ |
| 288 | base_size = offsetof(struct xfs_buf_log_format, blf_data_map) + | 288 | base_size = offsetof(struct xfs_buf_log_format, blf_data_map) + |
| 289 | (blfp->blf_map_size * sizeof(blfp->blf_data_map[0])); | 289 | (blfp->blf_map_size * sizeof(blfp->blf_data_map[0])); |
| 290 | |||
| 291 | nvecs = 0; | ||
| 292 | first_bit = xfs_next_bit(blfp->blf_data_map, blfp->blf_map_size, 0); | ||
| 293 | if (!(bip->bli_flags & XFS_BLI_STALE) && first_bit == -1) { | ||
| 294 | /* | ||
| 295 | * If the map is not be dirty in the transaction, mark | ||
| 296 | * the size as zero and do not advance the vector pointer. | ||
| 297 | */ | ||
| 298 | goto out; | ||
| 299 | } | ||
| 300 | |||
| 290 | vecp->i_addr = blfp; | 301 | vecp->i_addr = blfp; |
| 291 | vecp->i_len = base_size; | 302 | vecp->i_len = base_size; |
| 292 | vecp->i_type = XLOG_REG_TYPE_BFORMAT; | 303 | vecp->i_type = XLOG_REG_TYPE_BFORMAT; |
| @@ -301,15 +312,13 @@ xfs_buf_item_format_segment( | |||
| 301 | */ | 312 | */ |
| 302 | trace_xfs_buf_item_format_stale(bip); | 313 | trace_xfs_buf_item_format_stale(bip); |
| 303 | ASSERT(blfp->blf_flags & XFS_BLF_CANCEL); | 314 | ASSERT(blfp->blf_flags & XFS_BLF_CANCEL); |
| 304 | blfp->blf_size = nvecs; | 315 | goto out; |
| 305 | return vecp; | ||
| 306 | } | 316 | } |
| 307 | 317 | ||
| 308 | /* | 318 | /* |
| 309 | * Fill in an iovec for each set of contiguous chunks. | 319 | * Fill in an iovec for each set of contiguous chunks. |
| 310 | */ | 320 | */ |
| 311 | first_bit = xfs_next_bit(blfp->blf_data_map, blfp->blf_map_size, 0); | 321 | |
| 312 | ASSERT(first_bit != -1); | ||
| 313 | last_bit = first_bit; | 322 | last_bit = first_bit; |
| 314 | nbits = 1; | 323 | nbits = 1; |
| 315 | for (;;) { | 324 | for (;;) { |
| @@ -371,7 +380,8 @@ xfs_buf_item_format_segment( | |||
| 371 | nbits++; | 380 | nbits++; |
| 372 | } | 381 | } |
| 373 | } | 382 | } |
| 374 | bip->bli_format.blf_size = nvecs; | 383 | out: |
| 384 | blfp->blf_size = nvecs; | ||
| 375 | return vecp; | 385 | return vecp; |
| 376 | } | 386 | } |
| 377 | 387 | ||
| @@ -405,7 +415,7 @@ xfs_buf_item_format( | |||
| 405 | if (bip->bli_flags & XFS_BLI_INODE_BUF) { | 415 | if (bip->bli_flags & XFS_BLI_INODE_BUF) { |
| 406 | if (!((bip->bli_flags & XFS_BLI_INODE_ALLOC_BUF) && | 416 | if (!((bip->bli_flags & XFS_BLI_INODE_ALLOC_BUF) && |
| 407 | xfs_log_item_in_current_chkpt(lip))) | 417 | xfs_log_item_in_current_chkpt(lip))) |
| 408 | bip->bli_format.blf_flags |= XFS_BLF_INODE_BUF; | 418 | bip->__bli_format.blf_flags |= XFS_BLF_INODE_BUF; |
| 409 | bip->bli_flags &= ~XFS_BLI_INODE_BUF; | 419 | bip->bli_flags &= ~XFS_BLI_INODE_BUF; |
| 410 | } | 420 | } |
| 411 | 421 | ||
| @@ -485,7 +495,7 @@ xfs_buf_item_unpin( | |||
| 485 | ASSERT(bip->bli_flags & XFS_BLI_STALE); | 495 | ASSERT(bip->bli_flags & XFS_BLI_STALE); |
| 486 | ASSERT(xfs_buf_islocked(bp)); | 496 | ASSERT(xfs_buf_islocked(bp)); |
| 487 | ASSERT(XFS_BUF_ISSTALE(bp)); | 497 | ASSERT(XFS_BUF_ISSTALE(bp)); |
| 488 | ASSERT(bip->bli_format.blf_flags & XFS_BLF_CANCEL); | 498 | ASSERT(bip->__bli_format.blf_flags & XFS_BLF_CANCEL); |
| 489 | 499 | ||
| 490 | trace_xfs_buf_item_unpin_stale(bip); | 500 | trace_xfs_buf_item_unpin_stale(bip); |
| 491 | 501 | ||
| @@ -526,7 +536,25 @@ xfs_buf_item_unpin( | |||
| 526 | } | 536 | } |
| 527 | xfs_buf_relse(bp); | 537 | xfs_buf_relse(bp); |
| 528 | } else if (freed && remove) { | 538 | } else if (freed && remove) { |
| 539 | /* | ||
| 540 | * There are currently two references to the buffer - the active | ||
| 541 | * LRU reference and the buf log item. What we are about to do | ||
| 542 | * here - simulate a failed IO completion - requires 3 | ||
| 543 | * references. | ||
| 544 | * | ||
| 545 | * The LRU reference is removed by the xfs_buf_stale() call. The | ||
| 546 | * buf item reference is removed by the xfs_buf_iodone() | ||
| 547 | * callback that is run by xfs_buf_do_callbacks() during ioend | ||
| 548 | * processing (via the bp->b_iodone callback), and then finally | ||
| 549 | * the ioend processing will drop the IO reference if the buffer | ||
| 550 | * is marked XBF_ASYNC. | ||
| 551 | * | ||
| 552 | * Hence we need to take an additional reference here so that IO | ||
| 553 | * completion processing doesn't free the buffer prematurely. | ||
| 554 | */ | ||
| 529 | xfs_buf_lock(bp); | 555 | xfs_buf_lock(bp); |
| 556 | xfs_buf_hold(bp); | ||
| 557 | bp->b_flags |= XBF_ASYNC; | ||
| 530 | xfs_buf_ioerror(bp, EIO); | 558 | xfs_buf_ioerror(bp, EIO); |
| 531 | XFS_BUF_UNDONE(bp); | 559 | XFS_BUF_UNDONE(bp); |
| 532 | xfs_buf_stale(bp); | 560 | xfs_buf_stale(bp); |
| @@ -583,7 +611,7 @@ xfs_buf_item_unlock( | |||
| 583 | { | 611 | { |
| 584 | struct xfs_buf_log_item *bip = BUF_ITEM(lip); | 612 | struct xfs_buf_log_item *bip = BUF_ITEM(lip); |
| 585 | struct xfs_buf *bp = bip->bli_buf; | 613 | struct xfs_buf *bp = bip->bli_buf; |
| 586 | int aborted; | 614 | int aborted, clean, i; |
| 587 | uint hold; | 615 | uint hold; |
| 588 | 616 | ||
| 589 | /* Clear the buffer's association with this transaction. */ | 617 | /* Clear the buffer's association with this transaction. */ |
| @@ -613,7 +641,7 @@ xfs_buf_item_unlock( | |||
| 613 | */ | 641 | */ |
| 614 | if (bip->bli_flags & XFS_BLI_STALE) { | 642 | if (bip->bli_flags & XFS_BLI_STALE) { |
| 615 | trace_xfs_buf_item_unlock_stale(bip); | 643 | trace_xfs_buf_item_unlock_stale(bip); |
| 616 | ASSERT(bip->bli_format.blf_flags & XFS_BLF_CANCEL); | 644 | ASSERT(bip->__bli_format.blf_flags & XFS_BLF_CANCEL); |
| 617 | if (!aborted) { | 645 | if (!aborted) { |
| 618 | atomic_dec(&bip->bli_refcount); | 646 | atomic_dec(&bip->bli_refcount); |
| 619 | return; | 647 | return; |
| @@ -626,8 +654,15 @@ xfs_buf_item_unlock( | |||
| 626 | * If the buf item isn't tracking any data, free it, otherwise drop the | 654 | * If the buf item isn't tracking any data, free it, otherwise drop the |
| 627 | * reference we hold to it. | 655 | * reference we hold to it. |
| 628 | */ | 656 | */ |
| 629 | if (xfs_bitmap_empty(bip->bli_format.blf_data_map, | 657 | clean = 1; |
| 630 | bip->bli_format.blf_map_size)) | 658 | for (i = 0; i < bip->bli_format_count; i++) { |
| 659 | if (!xfs_bitmap_empty(bip->bli_formats[i].blf_data_map, | ||
| 660 | bip->bli_formats[i].blf_map_size)) { | ||
| 661 | clean = 0; | ||
| 662 | break; | ||
| 663 | } | ||
| 664 | } | ||
| 665 | if (clean) | ||
| 631 | xfs_buf_item_relse(bp); | 666 | xfs_buf_item_relse(bp); |
| 632 | else | 667 | else |
| 633 | atomic_dec(&bip->bli_refcount); | 668 | atomic_dec(&bip->bli_refcount); |
| @@ -698,7 +733,7 @@ xfs_buf_item_get_format( | |||
| 698 | bip->bli_format_count = count; | 733 | bip->bli_format_count = count; |
| 699 | 734 | ||
| 700 | if (count == 1) { | 735 | if (count == 1) { |
| 701 | bip->bli_formats = &bip->bli_format; | 736 | bip->bli_formats = &bip->__bli_format; |
| 702 | return 0; | 737 | return 0; |
| 703 | } | 738 | } |
| 704 | 739 | ||
| @@ -713,7 +748,7 @@ STATIC void | |||
| 713 | xfs_buf_item_free_format( | 748 | xfs_buf_item_free_format( |
| 714 | struct xfs_buf_log_item *bip) | 749 | struct xfs_buf_log_item *bip) |
| 715 | { | 750 | { |
| 716 | if (bip->bli_formats != &bip->bli_format) { | 751 | if (bip->bli_formats != &bip->__bli_format) { |
| 717 | kmem_free(bip->bli_formats); | 752 | kmem_free(bip->bli_formats); |
| 718 | bip->bli_formats = NULL; | 753 | bip->bli_formats = NULL; |
| 719 | } | 754 | } |
