Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

fs: Make bhs point to mapping_metadata_bhs

Make buffer heads point to mapping_metadata_bhs instead of struct
address_space. This makes the code more self contained. For the (only)
case of IO error handling where we really need to reach struct
address_space add a pointer to the mapping from mapping_metadata_bhs.

Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Jan Kara <jack@suse.cz>
Link: https://patch.msgid.link/20260326095354.16340-73-jack@suse.cz
Signed-off-by: Christian Brauner <brauner@kernel.org>

authored by

Jan Kara and committed by
Christian Brauner
c86f5d25 521bea7c

+20 -20
+16 -18
fs/buffer.c
··· 497 497 { 498 498 lockdep_assert_held(&mmb->lock); 499 499 list_del_init(&bh->b_assoc_buffers); 500 - WARN_ON(!bh->b_assoc_map); 501 - bh->b_assoc_map = NULL; 500 + WARN_ON(!bh->b_mmb); 501 + bh->b_mmb = NULL; 502 502 } 503 503 504 504 static void remove_assoc_queue(struct buffer_head *bh) 505 505 { 506 - struct address_space *mapping; 507 506 struct mapping_metadata_bhs *mmb; 508 507 509 508 /* ··· 513 514 * opportunistically acquire the lock and then recheck the bh 514 515 * didn't move under us. 515 516 */ 516 - while (bh->b_assoc_map) { 517 + while (bh->b_mmb) { 517 518 rcu_read_lock(); 518 - mapping = READ_ONCE(bh->b_assoc_map); 519 - if (mapping) { 520 - mmb = &mapping->i_metadata_bhs; 519 + mmb = READ_ONCE(bh->b_mmb); 520 + if (mmb) { 521 521 spin_lock(&mmb->lock); 522 - if (bh->b_assoc_map == mapping) 522 + if (bh->b_mmb == mmb) 523 523 __remove_assoc_queue(mmb, bh); 524 524 spin_unlock(&mmb->lock); 525 525 } ··· 549 551 * Do this in two main stages: first we copy dirty buffers to a 550 552 * temporary inode list, queueing the writes as we go. Then we clean 551 553 * up, waiting for those writes to complete. mark_buffer_dirty_inode() 552 - * doesn't touch b_assoc_buffers list if b_assoc_map is not NULL so we 553 - * are sure the buffer stays on our list until IO completes (at which point 554 - * it can be reaped). 554 + * doesn't touch b_assoc_buffers list if b_mmb is not NULL so we are sure the 555 + * buffer stays on our list until IO completes (at which point it can be 556 + * reaped). 555 557 */ 556 558 int sync_mapping_buffers(struct address_space *mapping) 557 559 { ··· 569 571 spin_lock(&mmb->lock); 570 572 while (!list_empty(&mmb->list)) { 571 573 bh = BH_ENTRY(mmb->list.next); 572 - WARN_ON_ONCE(bh->b_assoc_map != mapping); 574 + WARN_ON_ONCE(bh->b_mmb != mmb); 573 575 __remove_assoc_queue(mmb, bh); 574 576 /* Avoid race with mark_buffer_dirty_inode() which does 575 577 * a lockless check and we rely on seeing the dirty bit */ 576 578 smp_mb(); 577 579 if (buffer_dirty(bh) || buffer_locked(bh)) { 578 580 list_add(&bh->b_assoc_buffers, &tmp); 579 - bh->b_assoc_map = mapping; 581 + bh->b_mmb = mmb; 580 582 if (buffer_dirty(bh)) { 581 583 get_bh(bh); 582 584 spin_unlock(&mmb->lock); ··· 614 616 smp_mb(); 615 617 if (buffer_dirty(bh)) { 616 618 list_add(&bh->b_assoc_buffers, &mmb->list); 617 - bh->b_assoc_map = mapping; 619 + bh->b_mmb = mmb; 618 620 } 619 621 spin_unlock(&mmb->lock); 620 622 wait_on_buffer(bh); ··· 722 724 struct address_space *mapping = inode->i_mapping; 723 725 724 726 mark_buffer_dirty(bh); 725 - if (!bh->b_assoc_map) { 727 + if (!bh->b_mmb) { 726 728 spin_lock(&mapping->i_metadata_bhs.lock); 727 729 list_move_tail(&bh->b_assoc_buffers, 728 730 &mapping->i_metadata_bhs.list); 729 - bh->b_assoc_map = mapping; 731 + bh->b_mmb = &mapping->i_metadata_bhs; 730 732 spin_unlock(&mapping->i_metadata_bhs.lock); 731 733 } 732 734 } ··· 1122 1124 /* FIXME: do we need to set this in both places? */ 1123 1125 if (bh->b_folio && bh->b_folio->mapping) 1124 1126 mapping_set_error(bh->b_folio->mapping, -EIO); 1125 - if (bh->b_assoc_map) 1126 - mapping_set_error(bh->b_assoc_map, -EIO); 1127 + if (bh->b_mmb) 1128 + mapping_set_error(bh->b_mmb->mapping, -EIO); 1127 1129 } 1128 1130 EXPORT_SYMBOL(mark_buffer_write_io_error); 1129 1131
+1
fs/inode.c
··· 276 276 277 277 mapping->a_ops = &empty_aops; 278 278 mapping->host = inode; 279 + mapping->i_metadata_bhs.mapping = mapping; 279 280 mapping->flags = 0; 280 281 mapping->wb_err = 0; 281 282 atomic_set(&mapping->i_mmap_writable, 0);
+2 -2
include/linux/buffer_head.h
··· 73 73 bh_end_io_t *b_end_io; /* I/O completion */ 74 74 void *b_private; /* reserved for b_end_io */ 75 75 struct list_head b_assoc_buffers; /* associated with another mapping */ 76 - struct address_space *b_assoc_map; /* mapping this buffer is 77 - associated with */ 76 + struct mapping_metadata_bhs *b_mmb; /* head of the list of metadata bhs 77 + * this buffer is associated with */ 78 78 atomic_t b_count; /* users using this buffer_head */ 79 79 spinlock_t b_uptodate_lock; /* Used by the first bh in a page, to 80 80 * serialise IO completion of other
+1
include/linux/fs.h
··· 447 447 448 448 /* Structure for tracking metadata buffer heads associated with the mapping */ 449 449 struct mapping_metadata_bhs { 450 + struct address_space *mapping; /* Mapping bhs are associated with */ 450 451 spinlock_t lock; /* Lock protecting bh list */ 451 452 struct list_head list; /* The list of bhs (b_assoc_buffers) */ 452 453 };