* [PATCH 0/5] detect online disk resize
@ 2008-05-08 6:29 Andrew Patterson
2008-05-08 6:30 ` [PATCH 1/5] Wrapper for lower-level revalidate_disk routines Andrew Patterson
` (4 more replies)
0 siblings, 5 replies; 6+ messages in thread
From: Andrew Patterson @ 2008-05-08 6:29 UTC (permalink / raw)
To: linux-scsi; +Cc: andrew.patterson, linux-kernel, viro, axboe, andmike
This patch series handles online disk resizes that are currently not
completely recognized by the kernel using the existing revalidate_disk
routines. An online resize can occur when growing or shrinking a
Fibre Channel LUN or perhaps by adding a disk to an existing RAID
volume.
The kernel currently recognizes a device size change when
revalidate_disk() is called; however, the block layer does not use the
new size while it has any current openers on the device. So, for
example, if LVM has an volume open on the device, you will generally
not see the size change until after a reboot. We fix this problem by
creating a wrapper to be used with lower-level revalidate_disk
routines. This wrapper first calls the lower-level driver's
revalidate_disk routine. It then compares the gendisk capacity to the
block devices inode size. If there is a difference, we adjust the
block device's size. If the size has changed, we then flush the disk
for safety.
This patch series only modifies the sd driver to use these changes as
that is all that I currently have to test with. Device drivers like cciss
and DAC960 should probably use it as well.
Diff stats:
drivers/scsi/sd.c | 4 +--
fs/block_dev.c | 76 +++++++++++++++++++++++++++++++++++++++++++++++++---
include/linux/fs.h | 1 +
3 files changed, 74 insertions(+), 7 deletions(-)
Commits:
- Wrapper for lower-level revalidate_disk routines.
- Adjust block device size after an online resize of a disk.
- SCSI sd driver calls revalidate_disk wrapper.
- Added flush_disk to factor out common buffer cache flushing code.
- Call flush_disk() after detecting an online resize.
--
Andrew Patterson
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH 1/5] Wrapper for lower-level revalidate_disk routines.
2008-05-08 6:29 [PATCH 0/5] detect online disk resize Andrew Patterson
@ 2008-05-08 6:30 ` Andrew Patterson
2008-05-08 6:30 ` [PATCH 2/5] Adjust block device size after an online resize of a disk Andrew Patterson
` (3 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Andrew Patterson @ 2008-05-08 6:30 UTC (permalink / raw)
To: linux-scsi; +Cc: andrew.patterson, linux-kernel, viro, axboe, andmike
Wrapper for lower-level revalidate_disk routines.
This is a wrapper for the lower-level revalidate_disk call-backs such
as sd_revalidate_disk(). It allows us to perform pre and post
operations when calling them.
We will use this wrapper in a later patch to adjust block device sizes
after an online resize (a _post_ operation).
Signed-off-by: Andrew Patterson <andrew.patterson@hp.com>
---
fs/block_dev.c | 21 +++++++++++++++++++++
include/linux/fs.h | 1 +
2 files changed, 22 insertions(+), 0 deletions(-)
diff --git a/fs/block_dev.c b/fs/block_dev.c
index 7d822fa..72aaf59 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -867,6 +867,27 @@ struct block_device *open_by_devnum(dev_t dev, unsigned mode)
EXPORT_SYMBOL(open_by_devnum);
+/**
+ * revalidate_disk - wrapper for lower-level driver's revalidate_disk
+ * call-back
+ *
+ * @disk: struct gendisk to be revalidated
+ *
+ * This routine is a wrapper for lower-level driver's revalidate_disk
+ * call-backs. It is used to do common pre and post operations needed
+ * for all revalidate_disk operations.
+ */
+int revalidate_disk(struct gendisk *disk)
+{
+ int ret = 0;
+
+ if (disk->fops->revalidate_disk)
+ ret = disk->fops->revalidate_disk(disk);
+
+ return ret;
+}
+EXPORT_SYMBOL(revalidate_disk);
+
/*
* This routine checks whether a removable media has been changed,
* and invalidates all buffer-cache-entries in that case. This
diff --git a/include/linux/fs.h b/include/linux/fs.h
index a1ba005..bdc396c 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1709,6 +1709,7 @@ extern int fs_may_remount_ro(struct super_block *);
*/
#define bio_data_dir(bio) ((bio)->bi_rw & 1)
+extern int revalidate_disk(struct gendisk *);
extern int check_disk_change(struct block_device *);
extern int __invalidate_device(struct block_device *);
extern int invalidate_partition(struct gendisk *, int);
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH 2/5] Adjust block device size after an online resize of a disk.
2008-05-08 6:29 [PATCH 0/5] detect online disk resize Andrew Patterson
2008-05-08 6:30 ` [PATCH 1/5] Wrapper for lower-level revalidate_disk routines Andrew Patterson
@ 2008-05-08 6:30 ` Andrew Patterson
2008-05-08 6:31 ` [PATCH 3/5] SCSI sd driver calls revalidate_disk wrapper Andrew Patterson
` (2 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Andrew Patterson @ 2008-05-08 6:30 UTC (permalink / raw)
To: linux-scsi; +Cc: andrew.patterson, linux-kernel, viro, axboe, andmike
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>
---
fs/block_dev.c | 21 +++++++++++++++++++++
1 files changed, 21 insertions(+), 0 deletions(-)
diff --git a/fs/block_dev.c b/fs/block_dev.c
index 72aaf59..87014e6 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -879,11 +879,32 @@ EXPORT_SYMBOL(open_by_devnum);
*/
int revalidate_disk(struct gendisk *disk)
{
+ struct block_device *bdev;
+ loff_t disk_size, bdev_size;
int ret = 0;
if (disk->fops->revalidate_disk)
ret = disk->fops->revalidate_disk(disk);
+ bdev = bdget_disk(disk, 0);
+ if (!bdev)
+ return ret;
+
+ disk_size = (loff_t)get_capacity(disk) << 9;
+ mutex_lock(&bdev->bd_mutex);
+ bdev_size = i_size_read(bdev->bd_inode);
+ if (disk_size != bdev_size) {
+ char name[BDEVNAME_SIZE];
+
+ disk_name(disk, 0, name);
+ printk(KERN_INFO
+ "%s: detected capacity change from %lld to %lld\n",
+ name, bdev_size, disk_size);
+ i_size_write(bdev->bd_inode, disk_size);
+ }
+
+ mutex_unlock(&bdev->bd_mutex);
+ bdput(bdev);
return ret;
}
EXPORT_SYMBOL(revalidate_disk);
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH 3/5] SCSI sd driver calls revalidate_disk wrapper.
2008-05-08 6:29 [PATCH 0/5] detect online disk resize Andrew Patterson
2008-05-08 6:30 ` [PATCH 1/5] Wrapper for lower-level revalidate_disk routines Andrew Patterson
2008-05-08 6:30 ` [PATCH 2/5] Adjust block device size after an online resize of a disk Andrew Patterson
@ 2008-05-08 6:31 ` Andrew Patterson
2008-05-08 6:31 ` [PATCH 4/5] Added flush_disk to factor out common buffer cache flushing code Andrew Patterson
2008-05-08 6:32 ` [PATCH 5/5] Call flush_disk() after detecting an online resize Andrew Patterson
4 siblings, 0 replies; 6+ messages in thread
From: Andrew Patterson @ 2008-05-08 6:31 UTC (permalink / raw)
To: linux-scsi; +Cc: andrew.patterson, linux-kernel, viro, axboe, andmike
SCSI sd driver calls revalidate_disk wrapper.
Modify the SCSI disk driver to call the revalidate_disk()
wrapper. This allows us to do some housekeeping such as accounting for
a disk being resized online. The wrapper will call
sd_revalidate_disk() at the appropriate time.
Signed-off-by: Andrew Patterson <andrew.patterson@hp.com>
---
drivers/scsi/sd.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 01cefbb..7aedeb3 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -160,7 +160,7 @@ sd_store_cache_type(struct device *dev, struct device_attribute *attr,
sd_print_sense_hdr(sdkp, &sshdr);
return -EINVAL;
}
- sd_revalidate_disk(sdkp->disk);
+ revalidate_disk(sdkp->disk);
return count;
}
@@ -871,7 +871,7 @@ static void sd_rescan(struct device *dev)
struct scsi_disk *sdkp = scsi_disk_get_from_dev(dev);
if (sdkp) {
- sd_revalidate_disk(sdkp->disk);
+ revalidate_disk(sdkp->disk);
scsi_disk_put(sdkp);
}
}
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH 4/5] Added flush_disk to factor out common buffer cache flushing code.
2008-05-08 6:29 [PATCH 0/5] detect online disk resize Andrew Patterson
` (2 preceding siblings ...)
2008-05-08 6:31 ` [PATCH 3/5] SCSI sd driver calls revalidate_disk wrapper Andrew Patterson
@ 2008-05-08 6:31 ` Andrew Patterson
2008-05-08 6:32 ` [PATCH 5/5] Call flush_disk() after detecting an online resize Andrew Patterson
4 siblings, 0 replies; 6+ messages in thread
From: Andrew Patterson @ 2008-05-08 6:31 UTC (permalink / raw)
To: linux-scsi; +Cc: andrew.patterson, linux-kernel, viro, axboe, andmike
Added flush_disk to factor out common buffer cache flushing code.
We need to be able to flush the buffer cache for for more than
just when a disk is changed, so we factor out common cache flush code
in check_disk_change() to an internal flush_disk() routine. This
routine will then be used for both disk changes and disk resizes (in a
later patch).
Include the disk name in the text indicating that there are busy
inodes on the device and increase the KERN severity of the message.
Signed-off-by: Andrew Patterson <andrew.patterson@hp.com>
---
fs/block_dev.c | 33 ++++++++++++++++++++++++++++-----
1 files changed, 28 insertions(+), 5 deletions(-)
diff --git a/fs/block_dev.c b/fs/block_dev.c
index 87014e6..eb2bc5c 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -867,6 +867,33 @@ struct block_device *open_by_devnum(dev_t dev, unsigned mode)
EXPORT_SYMBOL(open_by_devnum);
+
+/**
+ * flush_disk - invalidates all buffer-cache entries on a disk
+ *
+ * @bdev: struct block device to be flushed
+ *
+ * Invalidates all buffer-cache entries on a disk. It should be called
+ * when a disk has been changed -- either by a media change or online
+ * resize.
+ */
+static void flush_disk(struct block_device *bdev)
+{
+ if (__invalidate_device(bdev)) {
+ char name[BDEVNAME_SIZE] = "";
+
+ if (bdev->bd_disk)
+ disk_name(bdev->bd_disk, 0, name);
+ printk(KERN_WARNING "VFS: busy inodes on changed media %s\n",
+ name);
+ }
+
+ if (!bdev->bd_disk)
+ return;
+ if (bdev->bd_disk->minors > 1)
+ bdev->bd_invalidated = 1;
+}
+
/**
* revalidate_disk - wrapper for lower-level driver's revalidate_disk
* call-back
@@ -928,13 +955,9 @@ int check_disk_change(struct block_device *bdev)
if (!bdops->media_changed(bdev->bd_disk))
return 0;
- if (__invalidate_device(bdev))
- printk("VFS: busy inodes on changed media.\n");
-
+ flush_disk(bdev);
if (bdops->revalidate_disk)
bdops->revalidate_disk(bdev->bd_disk);
- if (bdev->bd_disk->minors > 1)
- bdev->bd_invalidated = 1;
return 1;
}
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH 5/5] Call flush_disk() after detecting an online resize.
2008-05-08 6:29 [PATCH 0/5] detect online disk resize Andrew Patterson
` (3 preceding siblings ...)
2008-05-08 6:31 ` [PATCH 4/5] Added flush_disk to factor out common buffer cache flushing code Andrew Patterson
@ 2008-05-08 6:32 ` Andrew Patterson
4 siblings, 0 replies; 6+ messages in thread
From: Andrew Patterson @ 2008-05-08 6:32 UTC (permalink / raw)
To: linux-scsi; +Cc: andrew.patterson, linux-kernel, viro, axboe, andmike
Call flush_disk() after detecting an online resize.
We call flush_disk() to make sure the buffer cache for the disk is
flushed after a disk resize. There are two resize cases, growing and
shrinking. Given that users can shrink/then grow a disk before
revalidate_disk() is called, we treat the grow case identically to
shrinking. We need to flush the buffer cache after an online shrink
because, as James Bottomley puts it,
The two use cases for shrinking I can see are
1. planned: the fs is already shrunk to within the new boundaries
and all data is relocated, so invalidate is fine (any dirty
buffers that might exist in the shrunk region are there only
because they were relocated but not yet written to their
original location).
2. unplanned: In this case, the fs is probably toast, so whether
we invalidate or not isn't going to make a whole lot of
difference; it's still going to try to read or write from
sectors beyond the new size and get I/O errors.
Immediately invalidating shrunk disks will cause errors for outstanding
I/Os for reads/write beyond the new end of the disk to be generated
earlier then if we waited for the normal buffer cache operation. It also
removes a potential security hole where we might keep old data around
from beyond the end of the shrunk disk if the disk was not invalidated.
Signed-off-by: Andrew Patterson <andrew.patterson@hp.com>
---
fs/block_dev.c | 5 +++--
1 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/fs/block_dev.c b/fs/block_dev.c
index eb2bc5c..41ef08d 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -884,8 +884,8 @@ static void flush_disk(struct block_device *bdev)
if (bdev->bd_disk)
disk_name(bdev->bd_disk, 0, name);
- printk(KERN_WARNING "VFS: busy inodes on changed media %s\n",
- name);
+ printk(KERN_WARNING "VFS: busy inodes on changed media or "
+ "resized disk %s\n", name);
}
if (!bdev->bd_disk)
@@ -928,6 +928,7 @@ int revalidate_disk(struct gendisk *disk)
"%s: detected capacity change from %lld to %lld\n",
name, bdev_size, disk_size);
i_size_write(bdev->bd_inode, disk_size);
+ flush_disk(bdev);
}
mutex_unlock(&bdev->bd_mutex);
^ permalink raw reply related [flat|nested] 6+ messages in thread
end of thread, other threads:[~2008-05-08 6:32 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-05-08 6:29 [PATCH 0/5] detect online disk resize Andrew Patterson
2008-05-08 6:30 ` [PATCH 1/5] Wrapper for lower-level revalidate_disk routines Andrew Patterson
2008-05-08 6:30 ` [PATCH 2/5] Adjust block device size after an online resize of a disk Andrew Patterson
2008-05-08 6:31 ` [PATCH 3/5] SCSI sd driver calls revalidate_disk wrapper Andrew Patterson
2008-05-08 6:31 ` [PATCH 4/5] Added flush_disk to factor out common buffer cache flushing code Andrew Patterson
2008-05-08 6:32 ` [PATCH 5/5] Call flush_disk() after detecting an online resize Andrew Patterson
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox