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.

block: acquire q->limits_lock while reading sysfs attributes

There're few sysfs attributes(RW) whose store method is protected
with q->limits_lock, however the corresponding show method of these
attributes run holding q->sysfs_lock and that doesn't make sense
as ideally the show method of these attributes should also run
holding q->limits_lock instead of q->sysfs_lock. Hence update the
show method of these sysfs attributes so that reading of these
attributes acquire q->limits_lock instead of q->sysfs_lock.

Similarly, there're few sysfs attributes(RO) whose show method is
currently protected with q->sysfs_lock however updates to these
attributes could occur using atomic limit update APIs such as queue_
limits_start_update() and queue_limits_commit_update() which run
holding q->limits_lock. So that means that reading these attributes
holding q->sysfs_lock doesn't make sense. Hence update the show method
of these sysfs attributes(RO) such that they run with holding q->
limits_lock instead of q->sysfs_lock.

We have defined a new macro QUEUE_LIM_RO_ENTRY() which uses new ->show_
limit() method and it runs holding q->limits_lock. All existing sysfs
attributes(RO) which needs protection using q->limits_lock while
reading have been now updated to use this new macro for initialization.

Also, the existing QUEUE_LIM_RW_ENTRY() is updated to use new ->show_
limit() method for reading attributes instead of existing ->show()
method. As ->show_limit() runs holding q->limits_lock, the existing
sysfs attributes(RW) requiring protection are now inherently protected
using q->limits_lock instead of q->sysfs_lock.

Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Hannes Reinecke <hare@suse.de>
Reviewed-by: Ming Lei <ming.lei@redhat.com>
Signed-off-by: Nilay Shroff <nilay@linux.ibm.com>
Link: https://lore.kernel.org/r/20250304102551.2533767-2-nilay@linux.ibm.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>

authored by

Nilay Shroff and committed by
Jens Axboe
6e51a127 d301f164

+65 -37
+65 -37
block/blk-sysfs.c
··· 23 23 struct queue_sysfs_entry { 24 24 struct attribute attr; 25 25 ssize_t (*show)(struct gendisk *disk, char *page); 26 + ssize_t (*show_limit)(struct gendisk *disk, char *page); 27 + 26 28 ssize_t (*store)(struct gendisk *disk, const char *page, size_t count); 27 29 int (*store_limit)(struct gendisk *disk, const char *page, 28 30 size_t count, struct queue_limits *lim); 31 + 29 32 void (*load_module)(struct gendisk *disk, const char *page, size_t count); 30 33 }; 31 34 ··· 415 412 .store = _prefix##_store, \ 416 413 }; 417 414 415 + #define QUEUE_LIM_RO_ENTRY(_prefix, _name) \ 416 + static struct queue_sysfs_entry _prefix##_entry = { \ 417 + .attr = { .name = _name, .mode = 0444 }, \ 418 + .show_limit = _prefix##_show, \ 419 + } 420 + 418 421 #define QUEUE_LIM_RW_ENTRY(_prefix, _name) \ 419 422 static struct queue_sysfs_entry _prefix##_entry = { \ 420 423 .attr = { .name = _name, .mode = 0644 }, \ 421 - .show = _prefix##_show, \ 424 + .show_limit = _prefix##_show, \ 422 425 .store_limit = _prefix##_store, \ 423 426 } 424 427 ··· 439 430 QUEUE_RW_ENTRY(queue_requests, "nr_requests"); 440 431 QUEUE_RW_ENTRY(queue_ra, "read_ahead_kb"); 441 432 QUEUE_LIM_RW_ENTRY(queue_max_sectors, "max_sectors_kb"); 442 - QUEUE_RO_ENTRY(queue_max_hw_sectors, "max_hw_sectors_kb"); 443 - QUEUE_RO_ENTRY(queue_max_segments, "max_segments"); 444 - QUEUE_RO_ENTRY(queue_max_integrity_segments, "max_integrity_segments"); 445 - QUEUE_RO_ENTRY(queue_max_segment_size, "max_segment_size"); 433 + QUEUE_LIM_RO_ENTRY(queue_max_hw_sectors, "max_hw_sectors_kb"); 434 + QUEUE_LIM_RO_ENTRY(queue_max_segments, "max_segments"); 435 + QUEUE_LIM_RO_ENTRY(queue_max_integrity_segments, "max_integrity_segments"); 436 + QUEUE_LIM_RO_ENTRY(queue_max_segment_size, "max_segment_size"); 446 437 QUEUE_RW_LOAD_MODULE_ENTRY(elv_iosched, "scheduler"); 447 438 448 - QUEUE_RO_ENTRY(queue_logical_block_size, "logical_block_size"); 449 - QUEUE_RO_ENTRY(queue_physical_block_size, "physical_block_size"); 450 - QUEUE_RO_ENTRY(queue_chunk_sectors, "chunk_sectors"); 451 - QUEUE_RO_ENTRY(queue_io_min, "minimum_io_size"); 452 - QUEUE_RO_ENTRY(queue_io_opt, "optimal_io_size"); 439 + QUEUE_LIM_RO_ENTRY(queue_logical_block_size, "logical_block_size"); 440 + QUEUE_LIM_RO_ENTRY(queue_physical_block_size, "physical_block_size"); 441 + QUEUE_LIM_RO_ENTRY(queue_chunk_sectors, "chunk_sectors"); 442 + QUEUE_LIM_RO_ENTRY(queue_io_min, "minimum_io_size"); 443 + QUEUE_LIM_RO_ENTRY(queue_io_opt, "optimal_io_size"); 453 444 454 - QUEUE_RO_ENTRY(queue_max_discard_segments, "max_discard_segments"); 455 - QUEUE_RO_ENTRY(queue_discard_granularity, "discard_granularity"); 456 - QUEUE_RO_ENTRY(queue_max_hw_discard_sectors, "discard_max_hw_bytes"); 445 + QUEUE_LIM_RO_ENTRY(queue_max_discard_segments, "max_discard_segments"); 446 + QUEUE_LIM_RO_ENTRY(queue_discard_granularity, "discard_granularity"); 447 + QUEUE_LIM_RO_ENTRY(queue_max_hw_discard_sectors, "discard_max_hw_bytes"); 457 448 QUEUE_LIM_RW_ENTRY(queue_max_discard_sectors, "discard_max_bytes"); 458 449 QUEUE_RO_ENTRY(queue_discard_zeroes_data, "discard_zeroes_data"); 459 450 460 - QUEUE_RO_ENTRY(queue_atomic_write_max_sectors, "atomic_write_max_bytes"); 461 - QUEUE_RO_ENTRY(queue_atomic_write_boundary_sectors, 451 + QUEUE_LIM_RO_ENTRY(queue_atomic_write_max_sectors, "atomic_write_max_bytes"); 452 + QUEUE_LIM_RO_ENTRY(queue_atomic_write_boundary_sectors, 462 453 "atomic_write_boundary_bytes"); 463 - QUEUE_RO_ENTRY(queue_atomic_write_unit_max, "atomic_write_unit_max_bytes"); 464 - QUEUE_RO_ENTRY(queue_atomic_write_unit_min, "atomic_write_unit_min_bytes"); 454 + QUEUE_LIM_RO_ENTRY(queue_atomic_write_unit_max, "atomic_write_unit_max_bytes"); 455 + QUEUE_LIM_RO_ENTRY(queue_atomic_write_unit_min, "atomic_write_unit_min_bytes"); 465 456 466 457 QUEUE_RO_ENTRY(queue_write_same_max, "write_same_max_bytes"); 467 - QUEUE_RO_ENTRY(queue_max_write_zeroes_sectors, "write_zeroes_max_bytes"); 468 - QUEUE_RO_ENTRY(queue_max_zone_append_sectors, "zone_append_max_bytes"); 469 - QUEUE_RO_ENTRY(queue_zone_write_granularity, "zone_write_granularity"); 458 + QUEUE_LIM_RO_ENTRY(queue_max_write_zeroes_sectors, "write_zeroes_max_bytes"); 459 + QUEUE_LIM_RO_ENTRY(queue_max_zone_append_sectors, "zone_append_max_bytes"); 460 + QUEUE_LIM_RO_ENTRY(queue_zone_write_granularity, "zone_write_granularity"); 470 461 471 - QUEUE_RO_ENTRY(queue_zoned, "zoned"); 462 + QUEUE_LIM_RO_ENTRY(queue_zoned, "zoned"); 472 463 QUEUE_RO_ENTRY(queue_nr_zones, "nr_zones"); 473 - QUEUE_RO_ENTRY(queue_max_open_zones, "max_open_zones"); 474 - QUEUE_RO_ENTRY(queue_max_active_zones, "max_active_zones"); 464 + QUEUE_LIM_RO_ENTRY(queue_max_open_zones, "max_open_zones"); 465 + QUEUE_LIM_RO_ENTRY(queue_max_active_zones, "max_active_zones"); 475 466 476 467 QUEUE_RW_ENTRY(queue_nomerges, "nomerges"); 477 468 QUEUE_LIM_RW_ENTRY(queue_iostats_passthrough, "iostats_passthrough"); ··· 479 470 QUEUE_RW_ENTRY(queue_poll, "io_poll"); 480 471 QUEUE_RW_ENTRY(queue_poll_delay, "io_poll_delay"); 481 472 QUEUE_LIM_RW_ENTRY(queue_wc, "write_cache"); 482 - QUEUE_RO_ENTRY(queue_fua, "fua"); 483 - QUEUE_RO_ENTRY(queue_dax, "dax"); 473 + QUEUE_LIM_RO_ENTRY(queue_fua, "fua"); 474 + QUEUE_LIM_RO_ENTRY(queue_dax, "dax"); 484 475 QUEUE_RW_ENTRY(queue_io_timeout, "io_timeout"); 485 - QUEUE_RO_ENTRY(queue_virt_boundary_mask, "virt_boundary_mask"); 486 - QUEUE_RO_ENTRY(queue_dma_alignment, "dma_alignment"); 476 + QUEUE_LIM_RO_ENTRY(queue_virt_boundary_mask, "virt_boundary_mask"); 477 + QUEUE_LIM_RO_ENTRY(queue_dma_alignment, "dma_alignment"); 487 478 488 479 /* legacy alias for logical_block_size: */ 489 480 static struct queue_sysfs_entry queue_hw_sector_size_entry = { 490 - .attr = {.name = "hw_sector_size", .mode = 0444 }, 491 - .show = queue_logical_block_size_show, 481 + .attr = {.name = "hw_sector_size", .mode = 0444 }, 482 + .show_limit = queue_logical_block_size_show, 492 483 }; 493 484 494 485 QUEUE_LIM_RW_ENTRY(queue_rotational, "rotational"); ··· 570 561 571 562 /* Common attributes for bio-based and request-based queues. */ 572 563 static struct attribute *queue_attrs[] = { 573 - &queue_ra_entry.attr, 564 + /* 565 + * Attributes which are protected with q->limits_lock. 566 + */ 574 567 &queue_max_hw_sectors_entry.attr, 575 568 &queue_max_sectors_entry.attr, 576 569 &queue_max_segments_entry.attr, ··· 588 577 &queue_discard_granularity_entry.attr, 589 578 &queue_max_discard_sectors_entry.attr, 590 579 &queue_max_hw_discard_sectors_entry.attr, 591 - &queue_discard_zeroes_data_entry.attr, 592 580 &queue_atomic_write_max_sectors_entry.attr, 593 581 &queue_atomic_write_boundary_sectors_entry.attr, 594 582 &queue_atomic_write_unit_min_entry.attr, 595 583 &queue_atomic_write_unit_max_entry.attr, 596 - &queue_write_same_max_entry.attr, 597 584 &queue_max_write_zeroes_sectors_entry.attr, 598 585 &queue_max_zone_append_sectors_entry.attr, 599 586 &queue_zone_write_granularity_entry.attr, 600 587 &queue_rotational_entry.attr, 601 588 &queue_zoned_entry.attr, 602 - &queue_nr_zones_entry.attr, 603 589 &queue_max_open_zones_entry.attr, 604 590 &queue_max_active_zones_entry.attr, 605 - &queue_nomerges_entry.attr, 606 591 &queue_iostats_passthrough_entry.attr, 607 592 &queue_iostats_entry.attr, 608 593 &queue_stable_writes_entry.attr, 609 594 &queue_add_random_entry.attr, 610 - &queue_poll_entry.attr, 611 595 &queue_wc_entry.attr, 612 596 &queue_fua_entry.attr, 613 597 &queue_dax_entry.attr, 614 - &queue_poll_delay_entry.attr, 615 598 &queue_virt_boundary_mask_entry.attr, 616 599 &queue_dma_alignment_entry.attr, 600 + 601 + /* 602 + * Attributes which are protected with q->sysfs_lock. 603 + */ 604 + &queue_ra_entry.attr, 605 + &queue_discard_zeroes_data_entry.attr, 606 + &queue_write_same_max_entry.attr, 607 + &queue_nr_zones_entry.attr, 608 + &queue_nomerges_entry.attr, 609 + &queue_poll_entry.attr, 610 + &queue_poll_delay_entry.attr, 611 + 617 612 NULL, 618 613 }; 619 614 620 615 /* Request-based queue attributes that are not relevant for bio-based queues. */ 621 616 static struct attribute *blk_mq_queue_attrs[] = { 617 + /* 618 + * Attributes which are protected with q->sysfs_lock. 619 + */ 622 620 &queue_requests_entry.attr, 623 621 &elv_iosched_entry.attr, 624 622 &queue_rq_affinity_entry.attr, ··· 686 666 struct gendisk *disk = container_of(kobj, struct gendisk, queue_kobj); 687 667 ssize_t res; 688 668 689 - if (!entry->show) 669 + if (!entry->show && !entry->show_limit) 690 670 return -EIO; 671 + 672 + if (entry->show_limit) { 673 + mutex_lock(&disk->queue->limits_lock); 674 + res = entry->show_limit(disk, page); 675 + mutex_unlock(&disk->queue->limits_lock); 676 + return res; 677 + } 678 + 691 679 mutex_lock(&disk->queue->sysfs_lock); 692 680 res = entry->show(disk, page); 693 681 mutex_unlock(&disk->queue->sysfs_lock);