summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--block/partitions/core.c4
-rw-r--r--drivers/block/aoe/aoecmd.c4
-rw-r--r--drivers/md/dm.c15
-rw-r--r--drivers/s390/block/dasd_ioctl.c9
-rw-r--r--fs/block_dev.c25
-rw-r--r--include/linux/blk_types.h1
6 files changed, 22 insertions, 36 deletions
diff --git a/block/partitions/core.c b/block/partitions/core.c
index 5b4869c08fb3..b1c0b50ca92d 100644
--- a/block/partitions/core.c
+++ b/block/partitions/core.c
@@ -592,8 +592,8 @@ int bdev_resize_partition(struct block_device *bdev, int partno,
if (partition_overlaps(bdev->bd_disk, start, length, partno))
goto out_unlock;
- part_nr_sects_write(part, (sector_t)length);
- i_size_write(bdevp->bd_inode, length << SECTOR_SHIFT);
+ part_nr_sects_write(part, length);
+ bd_set_nr_sectors(bdevp, length);
ret = 0;
out_unlock:
diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c
index 6dba41395155..313f0b946fe2 100644
--- a/drivers/block/aoe/aoecmd.c
+++ b/drivers/block/aoe/aoecmd.c
@@ -900,9 +900,7 @@ aoecmd_sleepwork(struct work_struct *work)
ssize = get_capacity(d->gd);
bd = bdget_disk(d->gd, 0);
if (bd) {
- inode_lock(bd->bd_inode);
- i_size_write(bd->bd_inode, (loff_t)ssize<<9);
- inode_unlock(bd->bd_inode);
+ bd_set_nr_sectors(bd, ssize);
bdput(bd);
}
spin_lock_irq(&d->lock);
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index fb0255d25e4b..3dedd9cc4fb6 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -2098,18 +2098,6 @@ static void event_callback(void *context)
}
/*
- * Protected by md->suspend_lock obtained by dm_swap_table().
- */
-static void __set_size(struct mapped_device *md, sector_t size)
-{
- lockdep_assert_held(&md->suspend_lock);
-
- set_capacity(md->disk, size);
-
- i_size_write(md->bdev->bd_inode, (loff_t)size << SECTOR_SHIFT);
-}
-
-/*
* Returns old map, which caller must destroy.
*/
static struct dm_table *__bind(struct mapped_device *md, struct dm_table *t,
@@ -2131,7 +2119,8 @@ static struct dm_table *__bind(struct mapped_device *md, struct dm_table *t,
if (size != dm_get_size(md))
memset(&md->geometry, 0, sizeof(md->geometry));
- __set_size(md, size);
+ set_capacity(md->disk, size);
+ bd_set_nr_sectors(md->bdev, size);
dm_table_event_callback(t, event_callback, md);
diff --git a/drivers/s390/block/dasd_ioctl.c b/drivers/s390/block/dasd_ioctl.c
index 777734d1b4e5..faaf5596e31c 100644
--- a/drivers/s390/block/dasd_ioctl.c
+++ b/drivers/s390/block/dasd_ioctl.c
@@ -55,10 +55,7 @@ dasd_ioctl_enable(struct block_device *bdev)
dasd_enable_device(base);
/* Formatting the dasd device can change the capacity. */
- mutex_lock(&bdev->bd_mutex);
- i_size_write(bdev->bd_inode,
- (loff_t)get_capacity(base->block->gdp) << 9);
- mutex_unlock(&bdev->bd_mutex);
+ bd_set_nr_sectors(bdev, get_capacity(base->block->gdp));
dasd_put_device(base);
return 0;
}
@@ -91,9 +88,7 @@ dasd_ioctl_disable(struct block_device *bdev)
* Set i_size to zero, since read, write, etc. check against this
* value.
*/
- mutex_lock(&bdev->bd_mutex);
- i_size_write(bdev->bd_inode, 0);
- mutex_unlock(&bdev->bd_mutex);
+ bd_set_nr_sectors(bdev, 0);
dasd_put_device(base);
return 0;
}
diff --git a/fs/block_dev.c b/fs/block_dev.c
index f52597172c8b..08158bb2e76c 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -876,6 +876,7 @@ struct block_device *bdget(dev_t dev)
bdev = &BDEV_I(inode)->bdev;
if (inode->i_state & I_NEW) {
+ spin_lock_init(&bdev->bd_size_lock);
bdev->bd_contains = NULL;
bdev->bd_super = NULL;
bdev->bd_inode = inode;
@@ -1290,6 +1291,7 @@ static void check_disk_size_change(struct gendisk *disk,
{
loff_t disk_size, bdev_size;
+ spin_lock(&bdev->bd_size_lock);
disk_size = (loff_t)get_capacity(disk) << 9;
bdev_size = i_size_read(bdev->bd_inode);
if (disk_size != bdev_size) {
@@ -1299,11 +1301,15 @@ static void check_disk_size_change(struct gendisk *disk,
disk->disk_name, bdev_size, disk_size);
}
i_size_write(bdev->bd_inode, disk_size);
- if (bdev_size > disk_size && __invalidate_device(bdev, false))
+ }
+ bdev->bd_invalidated = 0;
+ spin_unlock(&bdev->bd_size_lock);
+
+ if (bdev_size > disk_size) {
+ if (__invalidate_device(bdev, false))
pr_warn("VFS: busy inodes on resized disk %s\n",
disk->disk_name);
}
- bdev->bd_invalidated = 0;
}
/**
@@ -1328,13 +1334,10 @@ int revalidate_disk(struct gendisk *disk)
if (!(disk->flags & GENHD_FL_HIDDEN)) {
struct block_device *bdev = bdget_disk(disk, 0);
- if (!bdev)
- return ret;
-
- mutex_lock(&bdev->bd_mutex);
- check_disk_size_change(disk, bdev, ret == 0);
- mutex_unlock(&bdev->bd_mutex);
- bdput(bdev);
+ if (bdev) {
+ check_disk_size_change(disk, bdev, ret == 0);
+ bdput(bdev);
+ }
}
return ret;
}
@@ -1373,9 +1376,9 @@ EXPORT_SYMBOL(check_disk_change);
void bd_set_nr_sectors(struct block_device *bdev, sector_t sectors)
{
- inode_lock(bdev->bd_inode);
+ spin_lock(&bdev->bd_size_lock);
i_size_write(bdev->bd_inode, (loff_t)sectors << SECTOR_SHIFT);
- inode_unlock(bdev->bd_inode);
+ spin_unlock(&bdev->bd_size_lock);
}
EXPORT_SYMBOL(bd_set_nr_sectors);
diff --git a/include/linux/blk_types.h b/include/linux/blk_types.h
index 4ecf4fed171f..5accc2549d22 100644
--- a/include/linux/blk_types.h
+++ b/include/linux/blk_types.h
@@ -38,6 +38,7 @@ struct block_device {
/* number of times partitions within this device have been opened. */
unsigned bd_part_count;
int bd_invalidated;
+ spinlock_t bd_size_lock; /* for bd_inode->i_size updates */
struct gendisk * bd_disk;
struct backing_dev_info *bd_bdi;