aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_buf_item.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/xfs/xfs_buf_item.c')
-rw-r--r--fs/xfs/xfs_buf_item.c67
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; 383out:
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
713xfs_buf_item_free_format( 748xfs_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 }