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.

loop: use READ_ONCE() to read lo->lo_state without locking

When lo->lo_mutex is not held, direct access may read stale data. This
patch uses READ_ONCE() to read lo->lo_state and data_race() to silence
code checkers, and changes all assignments to use WRITE_ONCE().

Reviewed-by: Damien Le Moal <dlemoal@kernel.org>
Signed-off-by: Yongpeng Yang <yangyongpeng@xiaomi.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Jens Axboe <axboe@kernel.dk>

authored by

Yongpeng Yang and committed by
Jens Axboe
54891a96 9869d3a6

+13 -9
+13 -9
drivers/block/loop.c
··· 1082 1082 /* Order wrt reading lo_state in loop_validate_file(). */ 1083 1083 wmb(); 1084 1084 1085 - lo->lo_state = Lo_bound; 1085 + WRITE_ONCE(lo->lo_state, Lo_bound); 1086 1086 if (part_shift) 1087 1087 lo->lo_flags |= LO_FLAGS_PARTSCAN; 1088 1088 partscan = lo->lo_flags & LO_FLAGS_PARTSCAN; ··· 1179 1179 if (!part_shift) 1180 1180 set_bit(GD_SUPPRESS_PART_SCAN, &lo->lo_disk->state); 1181 1181 mutex_lock(&lo->lo_mutex); 1182 - lo->lo_state = Lo_unbound; 1182 + WRITE_ONCE(lo->lo_state, Lo_unbound); 1183 1183 mutex_unlock(&lo->lo_mutex); 1184 1184 1185 1185 /* ··· 1218 1218 1219 1219 lo->lo_flags |= LO_FLAGS_AUTOCLEAR; 1220 1220 if (disk_openers(lo->lo_disk) == 1) 1221 - lo->lo_state = Lo_rundown; 1221 + WRITE_ONCE(lo->lo_state, Lo_rundown); 1222 1222 loop_global_unlock(lo, true); 1223 1223 1224 1224 return 0; ··· 1743 1743 1744 1744 mutex_lock(&lo->lo_mutex); 1745 1745 if (lo->lo_state == Lo_bound && (lo->lo_flags & LO_FLAGS_AUTOCLEAR)) 1746 - lo->lo_state = Lo_rundown; 1746 + WRITE_ONCE(lo->lo_state, Lo_rundown); 1747 1747 1748 1748 need_clear = (lo->lo_state == Lo_rundown); 1749 1749 mutex_unlock(&lo->lo_mutex); ··· 1858 1858 1859 1859 blk_mq_start_request(rq); 1860 1860 1861 - if (lo->lo_state != Lo_bound) 1861 + if (data_race(READ_ONCE(lo->lo_state)) != Lo_bound) 1862 1862 return BLK_STS_IOERR; 1863 1863 1864 1864 switch (req_op(rq)) { ··· 2016 2016 lo->worker_tree = RB_ROOT; 2017 2017 INIT_LIST_HEAD(&lo->idle_worker_list); 2018 2018 timer_setup(&lo->timer, loop_free_idle_workers_timer, TIMER_DEFERRABLE); 2019 - lo->lo_state = Lo_unbound; 2019 + WRITE_ONCE(lo->lo_state, Lo_unbound); 2020 2020 2021 2021 err = mutex_lock_killable(&loop_ctl_mutex); 2022 2022 if (err) ··· 2174 2174 goto mark_visible; 2175 2175 } 2176 2176 /* Mark this loop device as no more bound, but not quite unbound yet */ 2177 - lo->lo_state = Lo_deleting; 2177 + WRITE_ONCE(lo->lo_state, Lo_deleting); 2178 2178 mutex_unlock(&lo->lo_mutex); 2179 2179 2180 2180 loop_remove(lo); ··· 2197 2197 if (ret) 2198 2198 return ret; 2199 2199 idr_for_each_entry(&loop_index_idr, lo, id) { 2200 - /* Hitting a race results in creating a new loop device which is harmless. */ 2201 - if (lo->idr_visible && data_race(lo->lo_state) == Lo_unbound) 2200 + /* 2201 + * Hitting a race results in creating a new loop device 2202 + * which is harmless. 2203 + */ 2204 + if (lo->idr_visible && 2205 + data_race(READ_ONCE(lo->lo_state)) == Lo_unbound) 2202 2206 goto found; 2203 2207 } 2204 2208 mutex_unlock(&loop_ctl_mutex);