Skip to content

Commit

Permalink
aoe: don't call set_capacity from irq context
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Christoph Hellwig authored and Jens Axboe committed Nov 16, 2020
1 parent 2ebcabf commit 8a6f7bb
Showing 1 changed file with 4 additions and 11 deletions.
15 changes: 4 additions & 11 deletions drivers/block/aoe/aoecmd.c
Original file line number Diff line number Diff line change
Expand Up @@ -890,19 +890,13 @@ void
aoecmd_sleepwork(struct work_struct *work)
{
struct aoedev *d = container_of(work, struct aoedev, work);
struct block_device *bd;
u64 ssize;

if (d->flags & DEVFL_GDALLOC)
aoeblk_gdalloc(d);

if (d->flags & DEVFL_NEWSIZE) {
ssize = get_capacity(d->gd);
bd = bdget_disk(d->gd, 0);
if (bd) {
bd_set_nr_sectors(bd, ssize);
bdput(bd);
}
set_capacity_and_notify(d->gd, d->ssize);

spin_lock_irq(&d->lock);
d->flags |= DEVFL_UP;
d->flags &= ~DEVFL_NEWSIZE;
Expand Down Expand Up @@ -971,10 +965,9 @@ ataid_complete(struct aoedev *d, struct aoetgt *t, unsigned char *id)
d->geo.start = 0;
if (d->flags & (DEVFL_GDALLOC|DEVFL_NEWSIZE))
return;
if (d->gd != NULL) {
set_capacity(d->gd, ssize);
if (d->gd != NULL)
d->flags |= DEVFL_NEWSIZE;
} else
else
d->flags |= DEVFL_GDALLOC;
schedule_work(&d->work);
}
Expand Down

0 comments on commit 8a6f7bb

Please sign in to comment.