Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

aoe: don't call set_capacity from irq context

Updating the block device size from irq context can lead to torn
writes of the 64-bit value, and prevents us from using normal
process context locking primitives to serialize access to the 64-bit
nr_sectors value. Defer the set_capacity to the already existing
workqueue handler, where it can be merged with the update of the
block device size by using set_capacity_and_notify. As an extra
bonus this also adds proper uevent notifications for the resize.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Jens Axboe <axboe@kernel.dk>

authored by

Christoph Hellwig and committed by
Jens Axboe
8a6f7bbf 2ebcabf3

+4 -11
+4 -11
drivers/block/aoe/aoecmd.c
··· 890 890 aoecmd_sleepwork(struct work_struct *work) 891 891 { 892 892 struct aoedev *d = container_of(work, struct aoedev, work); 893 - struct block_device *bd; 894 - u64 ssize; 895 893 896 894 if (d->flags & DEVFL_GDALLOC) 897 895 aoeblk_gdalloc(d); 898 896 899 897 if (d->flags & DEVFL_NEWSIZE) { 900 - ssize = get_capacity(d->gd); 901 - bd = bdget_disk(d->gd, 0); 902 - if (bd) { 903 - bd_set_nr_sectors(bd, ssize); 904 - bdput(bd); 905 - } 898 + set_capacity_and_notify(d->gd, d->ssize); 899 + 906 900 spin_lock_irq(&d->lock); 907 901 d->flags |= DEVFL_UP; 908 902 d->flags &= ~DEVFL_NEWSIZE; ··· 965 971 d->geo.start = 0; 966 972 if (d->flags & (DEVFL_GDALLOC|DEVFL_NEWSIZE)) 967 973 return; 968 - if (d->gd != NULL) { 969 - set_capacity(d->gd, ssize); 974 + if (d->gd != NULL) 970 975 d->flags |= DEVFL_NEWSIZE; 971 - } else 976 + else 972 977 d->flags |= DEVFL_GDALLOC; 973 978 schedule_work(&d->work); 974 979 }