Commit c3279d1454cdfed02a557d789d8a6d08ab4cbe70

Authored by Andrew Patterson
Committed by Jens Axboe
1 parent 0c002c2f74

Adjust block device size after an online resize of a disk.

The revalidate_disk routine now checks if a disk has been resized by
comparing the gendisk capacity to the bdev inode size.  If they are
different (usually because the disk has been resized underneath the kernel)
the bdev inode size is adjusted to match the capacity.

Signed-off-by: Andrew Patterson <andrew.patterson@hp.com>
Signed-off-by: Jens Axboe <jens.axboe@oracle.com>

Showing 2 changed files with 39 additions and 0 deletions Side-by-side Diff

... ... @@ -853,6 +853,34 @@
853 853 EXPORT_SYMBOL(open_by_devnum);
854 854  
855 855 /**
  856 + * check_disk_size_change - checks for disk size change and adjusts
  857 + * bdev size.
  858 + *
  859 + * @disk: struct gendisk to check
  860 + * @bdev: struct bdev to adjust.
  861 + *
  862 + * This routine checks to see if the bdev size does not match the disk size
  863 + * and adjusts it if it differs.
  864 + */
  865 +void check_disk_size_change(struct gendisk *disk, struct block_device *bdev)
  866 +{
  867 + loff_t disk_size, bdev_size;
  868 +
  869 + disk_size = (loff_t)get_capacity(disk) << 9;
  870 + bdev_size = i_size_read(bdev->bd_inode);
  871 + if (disk_size != bdev_size) {
  872 + char name[BDEVNAME_SIZE];
  873 +
  874 + disk_name(disk, 0, name);
  875 + printk(KERN_INFO
  876 + "%s: detected capacity change from %lld to %lld\n",
  877 + name, bdev_size, disk_size);
  878 + i_size_write(bdev->bd_inode, disk_size);
  879 + }
  880 +}
  881 +EXPORT_SYMBOL(check_disk_size_change);
  882 +
  883 +/**
856 884 * revalidate_disk - wrapper for lower-level driver's revalidate_disk
857 885 * call-back
858 886 *
859 887  
... ... @@ -864,11 +892,20 @@
864 892 */
865 893 int revalidate_disk(struct gendisk *disk)
866 894 {
  895 + struct block_device *bdev;
867 896 int ret = 0;
868 897  
869 898 if (disk->fops->revalidate_disk)
870 899 ret = disk->fops->revalidate_disk(disk);
871 900  
  901 + bdev = bdget_disk(disk, 0);
  902 + if (!bdev)
  903 + return ret;
  904 +
  905 + mutex_lock(&bdev->bd_mutex);
  906 + check_disk_size_change(disk, bdev);
  907 + mutex_unlock(&bdev->bd_mutex);
  908 + bdput(bdev);
872 909 return ret;
873 910 }
874 911 EXPORT_SYMBOL(revalidate_disk);
... ... @@ -1722,6 +1722,8 @@
1722 1722 */
1723 1723 #define bio_data_dir(bio) ((bio)->bi_rw & 1)
1724 1724  
  1725 +extern void check_disk_size_change(struct gendisk *disk,
  1726 + struct block_device *bdev);
1725 1727 extern int revalidate_disk(struct gendisk *);
1726 1728 extern int check_disk_change(struct block_device *);
1727 1729 extern int __invalidate_device(struct block_device *);