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: fix NULL pointer dereference in blk_zone_reset_all_bio_endio()

For zoned block devices that do not need zone write plugs (e.g. most
device mapper devices that support zones), the disk hash table of zone
write plugs is NULL. For such devices, blk_zone_reset_all_bio_endio()
should not attempt to scan this has table as that causes a NULL pointer
dereference.

Fix this by checking that the disk does have zone write plugs using the
atomic counter. This is equivalent to checking for a non-NULL hash table
but has the advantage to also speed up the execution of
blk_zone_reset_all_bio_endio() for devices that do use zone write plugs
but do not have any plug in the hash table (e.g. a disk with only full
zones).

Fixes: efae226c2ef1 ("block: handle zone management operations completions")
Reported-by: Shin'ichiro Kawasaki <shinichiro.kawasaki@wdc.com>
Signed-off-by: Damien Le Moal <dlemoal@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Jens Axboe <axboe@kernel.dk>

authored by

Damien Le Moal and committed by
Jens Axboe
c2b8d206 f2333391

+12 -9
+12 -9
block/blk-zoned.c
··· 1118 1118 sector_t sector; 1119 1119 unsigned int i; 1120 1120 1121 - /* Update the condition of all zone write plugs. */ 1122 - rcu_read_lock(); 1123 - for (i = 0; i < disk_zone_wplugs_hash_size(disk); i++) { 1124 - hlist_for_each_entry_rcu(zwplug, &disk->zone_wplugs_hash[i], 1125 - node) { 1126 - spin_lock_irqsave(&zwplug->lock, flags); 1127 - disk_zone_wplug_set_wp_offset(disk, zwplug, 0); 1128 - spin_unlock_irqrestore(&zwplug->lock, flags); 1121 + if (atomic_read(&disk->nr_zone_wplugs)) { 1122 + /* Update the condition of all zone write plugs. */ 1123 + rcu_read_lock(); 1124 + for (i = 0; i < disk_zone_wplugs_hash_size(disk); i++) { 1125 + hlist_for_each_entry_rcu(zwplug, 1126 + &disk->zone_wplugs_hash[i], 1127 + node) { 1128 + spin_lock_irqsave(&zwplug->lock, flags); 1129 + disk_zone_wplug_set_wp_offset(disk, zwplug, 0); 1130 + spin_unlock_irqrestore(&zwplug->lock, flags); 1131 + } 1129 1132 } 1133 + rcu_read_unlock(); 1130 1134 } 1131 - rcu_read_unlock(); 1132 1135 1133 1136 /* Update the cached zone conditions. */ 1134 1137 for (sector = 0; sector < capacity;