]>
Commit | Line | Data |
---|---|---|
1 | Subject: Adjust block device size after an online resize of a disk. | |
2 | From: Andrew Patterson <andrew.patterson@hp.com> | |
3 | Date: Thu Oct 9 08:56:12 2008 +0200: | |
4 | Git: c3279d1454cdfed02a557d789d8a6d08ab4cbe70 | |
5 | References: FATE#302348,FATE#303786 | |
6 | ||
7 | The revalidate_disk routine now checks if a disk has been resized by | |
8 | comparing the gendisk capacity to the bdev inode size. If they are | |
9 | different (usually because the disk has been resized underneath the kernel) | |
10 | the bdev inode size is adjusted to match the capacity. | |
11 | ||
12 | Signed-off-by: Andrew Patterson <andrew.patterson@hp.com> | |
13 | Signed-off-by: Jens Axboe <jens.axboe@oracle.com> | |
14 | Signed-off-by: Hannes Reinecke <hare@suse.de> | |
15 | --- | |
16 | fs/block_dev.c | 37 +++++++++++++++++++++++++++++++++++++ | |
17 | include/linux/fs.h | 2 ++ | |
18 | 2 files changed, 39 insertions(+) | |
19 | ||
20 | --- a/fs/block_dev.c | |
21 | +++ b/fs/block_dev.c | |
22 | @@ -869,6 +869,34 @@ struct block_device *open_by_devnum(dev_ | |
23 | EXPORT_SYMBOL(open_by_devnum); | |
24 | ||
25 | /** | |
26 | + * check_disk_size_change - checks for disk size change and adjusts | |
27 | + * bdev size. | |
28 | + * | |
29 | + * @disk: struct gendisk to check | |
30 | + * @bdev: struct bdev to adjust. | |
31 | + * | |
32 | + * This routine checks to see if the bdev size does not match the disk size | |
33 | + * and adjusts it if it differs. | |
34 | + */ | |
35 | +void check_disk_size_change(struct gendisk *disk, struct block_device *bdev) | |
36 | +{ | |
37 | + loff_t disk_size, bdev_size; | |
38 | + | |
39 | + disk_size = (loff_t)get_capacity(disk) << 9; | |
40 | + bdev_size = i_size_read(bdev->bd_inode); | |
41 | + if (disk_size != bdev_size) { | |
42 | + char name[BDEVNAME_SIZE]; | |
43 | + | |
44 | + disk_name(disk, 0, name); | |
45 | + printk(KERN_INFO | |
46 | + "%s: detected capacity change from %lld to %lld\n", | |
47 | + name, bdev_size, disk_size); | |
48 | + i_size_write(bdev->bd_inode, disk_size); | |
49 | + } | |
50 | +} | |
51 | +EXPORT_SYMBOL(check_disk_size_change); | |
52 | + | |
53 | +/** | |
54 | * revalidate_disk - wrapper for lower-level driver's revalidate_disk | |
55 | * call-back | |
56 | * | |
57 | @@ -880,11 +908,20 @@ EXPORT_SYMBOL(open_by_devnum); | |
58 | */ | |
59 | int revalidate_disk(struct gendisk *disk) | |
60 | { | |
61 | + struct block_device *bdev; | |
62 | int ret = 0; | |
63 | ||
64 | if (disk->fops->revalidate_disk) | |
65 | ret = disk->fops->revalidate_disk(disk); | |
66 | ||
67 | + bdev = bdget_disk(disk, 0); | |
68 | + if (!bdev) | |
69 | + return ret; | |
70 | + | |
71 | + mutex_lock(&bdev->bd_mutex); | |
72 | + check_disk_size_change(disk, bdev); | |
73 | + mutex_unlock(&bdev->bd_mutex); | |
74 | + bdput(bdev); | |
75 | return ret; | |
76 | } | |
77 | EXPORT_SYMBOL(revalidate_disk); | |
78 | --- a/include/linux/fs.h | |
79 | +++ b/include/linux/fs.h | |
80 | @@ -1742,6 +1742,8 @@ extern int fs_may_remount_ro(struct supe | |
81 | */ | |
82 | #define bio_data_dir(bio) ((bio)->bi_rw & 1) | |
83 | ||
84 | +extern void check_disk_size_change(struct gendisk *disk, | |
85 | + struct block_device *bdev); | |
86 | extern int revalidate_disk(struct gendisk *); | |
87 | extern int check_disk_change(struct block_device *); | |
88 | extern int __invalidate_device(struct block_device *); |