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>
This commit is contained in:
committed by
Jens Axboe
parent
2ebcabf3db
commit
8a6f7bbf29
@@ -890,19 +890,13 @@ void
|
|||||||
aoecmd_sleepwork(struct work_struct *work)
|
aoecmd_sleepwork(struct work_struct *work)
|
||||||
{
|
{
|
||||||
struct aoedev *d = container_of(work, struct aoedev, work);
|
struct aoedev *d = container_of(work, struct aoedev, work);
|
||||||
struct block_device *bd;
|
|
||||||
u64 ssize;
|
|
||||||
|
|
||||||
if (d->flags & DEVFL_GDALLOC)
|
if (d->flags & DEVFL_GDALLOC)
|
||||||
aoeblk_gdalloc(d);
|
aoeblk_gdalloc(d);
|
||||||
|
|
||||||
if (d->flags & DEVFL_NEWSIZE) {
|
if (d->flags & DEVFL_NEWSIZE) {
|
||||||
ssize = get_capacity(d->gd);
|
set_capacity_and_notify(d->gd, d->ssize);
|
||||||
bd = bdget_disk(d->gd, 0);
|
|
||||||
if (bd) {
|
|
||||||
bd_set_nr_sectors(bd, ssize);
|
|
||||||
bdput(bd);
|
|
||||||
}
|
|
||||||
spin_lock_irq(&d->lock);
|
spin_lock_irq(&d->lock);
|
||||||
d->flags |= DEVFL_UP;
|
d->flags |= DEVFL_UP;
|
||||||
d->flags &= ~DEVFL_NEWSIZE;
|
d->flags &= ~DEVFL_NEWSIZE;
|
||||||
@@ -971,10 +965,9 @@ ataid_complete(struct aoedev *d, struct aoetgt *t, unsigned char *id)
|
|||||||
d->geo.start = 0;
|
d->geo.start = 0;
|
||||||
if (d->flags & (DEVFL_GDALLOC|DEVFL_NEWSIZE))
|
if (d->flags & (DEVFL_GDALLOC|DEVFL_NEWSIZE))
|
||||||
return;
|
return;
|
||||||
if (d->gd != NULL) {
|
if (d->gd != NULL)
|
||||||
set_capacity(d->gd, ssize);
|
|
||||||
d->flags |= DEVFL_NEWSIZE;
|
d->flags |= DEVFL_NEWSIZE;
|
||||||
} else
|
else
|
||||||
d->flags |= DEVFL_GDALLOC;
|
d->flags |= DEVFL_GDALLOC;
|
||||||
schedule_work(&d->work);
|
schedule_work(&d->work);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user