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.

Merge tag 'block-6.11-20240912' of git://git.kernel.dk/linux

Pull block fix from Jens Axboe:
"Just a single fix for a deadlock issue that can happen if someone
attempts to change the root disk IO scheduler with a module that
requires loading from disk.

Changing the scheduler freezes the queue while that operation is
happening, hence causing a deadlock"

* tag 'block-6.11-20240912' of git://git.kernel.dk/linux:
block: Prevent deadlocks when switching elevators

+38 -7
+21 -1
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 + int (*load_module)(struct gendisk *disk, const char *page, size_t count); 26 27 ssize_t (*store)(struct gendisk *disk, const char *page, size_t count); 27 28 }; 28 29 ··· 414 413 .store = _prefix##_store, \ 415 414 }; 416 415 416 + #define QUEUE_RW_LOAD_MODULE_ENTRY(_prefix, _name) \ 417 + static struct queue_sysfs_entry _prefix##_entry = { \ 418 + .attr = { .name = _name, .mode = 0644 }, \ 419 + .show = _prefix##_show, \ 420 + .load_module = _prefix##_load_module, \ 421 + .store = _prefix##_store, \ 422 + } 423 + 417 424 QUEUE_RW_ENTRY(queue_requests, "nr_requests"); 418 425 QUEUE_RW_ENTRY(queue_ra, "read_ahead_kb"); 419 426 QUEUE_RW_ENTRY(queue_max_sectors, "max_sectors_kb"); ··· 429 420 QUEUE_RO_ENTRY(queue_max_segments, "max_segments"); 430 421 QUEUE_RO_ENTRY(queue_max_integrity_segments, "max_integrity_segments"); 431 422 QUEUE_RO_ENTRY(queue_max_segment_size, "max_segment_size"); 432 - QUEUE_RW_ENTRY(elv_iosched, "scheduler"); 423 + QUEUE_RW_LOAD_MODULE_ENTRY(elv_iosched, "scheduler"); 433 424 434 425 QUEUE_RO_ENTRY(queue_logical_block_size, "logical_block_size"); 435 426 QUEUE_RO_ENTRY(queue_physical_block_size, "physical_block_size"); ··· 678 669 679 670 if (!entry->store) 680 671 return -EIO; 672 + 673 + /* 674 + * If the attribute needs to load a module, do it before freezing the 675 + * queue to ensure that the module file can be read when the request 676 + * queue is the one for the device storing the module file. 677 + */ 678 + if (entry->load_module) { 679 + res = entry->load_module(disk, page, length); 680 + if (res) 681 + return res; 682 + } 681 683 682 684 blk_mq_freeze_queue(q); 683 685 mutex_lock(&q->sysfs_lock);
+15 -6
block/elevator.c
··· 698 698 return 0; 699 699 700 700 e = elevator_find_get(q, elevator_name); 701 - if (!e) { 702 - request_module("%s-iosched", elevator_name); 703 - e = elevator_find_get(q, elevator_name); 704 - if (!e) 705 - return -EINVAL; 706 - } 701 + if (!e) 702 + return -EINVAL; 707 703 ret = elevator_switch(q, e); 708 704 elevator_put(e); 709 705 return ret; 706 + } 707 + 708 + int elv_iosched_load_module(struct gendisk *disk, const char *buf, 709 + size_t count) 710 + { 711 + char elevator_name[ELV_NAME_MAX]; 712 + 713 + if (!elv_support_iosched(disk->queue)) 714 + return -EOPNOTSUPP; 715 + 716 + strscpy(elevator_name, buf, sizeof(elevator_name)); 717 + 718 + return request_module("%s-iosched", strstrip(elevator_name)); 710 719 } 711 720 712 721 ssize_t elv_iosched_store(struct gendisk *disk, const char *buf,
+2
block/elevator.h
··· 148 148 * io scheduler sysfs switching 149 149 */ 150 150 ssize_t elv_iosched_show(struct gendisk *disk, char *page); 151 + int elv_iosched_load_module(struct gendisk *disk, const char *page, 152 + size_t count); 151 153 ssize_t elv_iosched_store(struct gendisk *disk, const char *page, size_t count); 152 154 153 155 extern bool elv_bio_merge_ok(struct request *, struct bio *);