Commit 8a6f7bbf authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Jens Axboe
Browse files

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: default avatarChristoph Hellwig <hch@lst.de>
Signed-off-by: default avatarJens Axboe <axboe@kernel.dk>
parent 2ebcabf3
Loading
Loading
Loading
Loading
+4 −11
Original line number Diff line number Diff line
@@ -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;
@@ -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);
}