summaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorAhmed S. Darwish <a.darwish@linutronix.de>2020-06-03 16:49:48 +0200
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2020-06-25 15:33:07 +0200
commite1906ca16db5d2b28dffd5785f058d22dbea1ab4 (patch)
tree86e3a2f9919857824ae66d74a1c622f4f71168d1 /include
parent4cc4e2dbf958a0bb7a0f3b05c79fc4232d3c2398 (diff)
downloadlinux-stable-e1906ca16db5d2b28dffd5785f058d22dbea1ab4.tar.gz
linux-stable-e1906ca16db5d2b28dffd5785f058d22dbea1ab4.tar.bz2
linux-stable-e1906ca16db5d2b28dffd5785f058d22dbea1ab4.zip
block: nr_sects_write(): Disable preemption on seqcount write
[ Upstream commit 15b81ce5abdc4b502aa31dff2d415b79d2349d2f ] For optimized block readers not holding a mutex, the "number of sectors" 64-bit value is protected from tearing on 32-bit architectures by a sequence counter. Disable preemption before entering that sequence counter's write side critical section. Otherwise, the read side can preempt the write side section and spin for the entire scheduler tick. If the reader belongs to a real-time scheduling class, it can spin forever and the kernel will livelock. Fixes: c83f6bf98dc1 ("block: add partition resize function to blkpg ioctl") Cc: <stable@vger.kernel.org> Signed-off-by: Ahmed S. Darwish <a.darwish@linutronix.de> Reviewed-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> Signed-off-by: Jens Axboe <axboe@kernel.dk> Signed-off-by: Sasha Levin <sashal@kernel.org>
Diffstat (limited to 'include')
-rw-r--r--include/linux/genhd.h2
1 files changed, 2 insertions, 0 deletions
diff --git a/include/linux/genhd.h b/include/linux/genhd.h
index f13272d84332..f993bc86f3ba 100644
--- a/include/linux/genhd.h
+++ b/include/linux/genhd.h
@@ -729,9 +729,11 @@ static inline sector_t part_nr_sects_read(struct hd_struct *part)
static inline void part_nr_sects_write(struct hd_struct *part, sector_t size)
{
#if BITS_PER_LONG==32 && defined(CONFIG_LBDAF) && defined(CONFIG_SMP)
+ preempt_disable();
write_seqcount_begin(&part->nr_sects_seq);
part->nr_sects = size;
write_seqcount_end(&part->nr_sects_seq);
+ preempt_enable();
#elif BITS_PER_LONG==32 && defined(CONFIG_LBDAF) && defined(CONFIG_PREEMPT)
preempt_disable();
part->nr_sects = size;