hot scsi disk resize
Hello!
Here is patch to implement hot scsi resize function. Modern storage boxes support virtualization feature and may change logical volume size online. I think it would be great if linux supports such abilities. Look at this example:
root@zefir:# dmesg | tail scsi0:A:1:0: Tagged Queuing enabled. Depth 32 SCSI device sda: 2097152 512-byte hdwr sectors (1074 MB) SCSI device sda: drive cache: write through sda: unknown partition table Attached scsi disk sda at scsi0, channel 0, id 1, lun 0
root@zefir:# mount -treiserfs /dev/sda /mnt
root@zefir:# df -Th Filesystem Type Size Used Avail Use% Mounted on /dev/hda1 ext3 1.9G 1.8G 138M 93% / /dev/sda reiserfs 1.0G 33M 991M 4% /mnt
root@zefir:# echo 'scsi rescan 0 0 1 0' >/proc/scsi/scsi root@zefir:# dmesg|tail -n1 SCSI device sda: 20971520 512-byte hdwr sectors (10737 MB) root@zefir:# resize_reiserfs /dev/sda
<-------------resize_reiserfs, 2002------------->
reiserfsprogs 3.6.4
root@zefir:# df -Th Filesystem Type Size Used Avail Use% Mounted on /dev/hda1 ext3 1.9G 1.8G 138M 93% / /dev/sda reiserfs 10G 33M 9.9G 1% /mnt
I think it's really useful for for high-availability systems. MS Windows has supported online disk resize since 2000. I Would be happy to hear any comments and suggestions.
drivers/scsi/hosts.h +1 -0
@@ -558,6 +558,7 @@void (*detach)(Scsi_Device *);int (*init_command)(Scsi_Cmnd *);/* Used by new queueing code. Selects command for blkdevs */ +void (*rescan)(Scsi_Device *);struct device_driver scsi_driverfs_driver; };
drivers/scsi/scsi.c +15 -0
@@ -1510,6 +1510,21 @@up_read (&scsi_devicelist_mutex); } +void scsi_rescan_device (struct scsi_device *sdev) +{ +struct Scsi_Device_Template *sdt; + +down_read (&scsi_devicelist_mutex); +list_for_each_entry (sdt, &scsi_devicelist, list) { +if (!try_module_get (sdt->module)) +continue ; +if (*sdt->rescan) + (*sdt->rescan)(sdev); +module_put (sdt->module); + } +up_read (&scsi_devicelist_mutex); +} +int scsi_device_get (struct scsi_device *sdev) {if (!try_module_get (sdev->host->hostt->module))
drivers/scsi/scsi_proc.c +12 -0
@@ -551,6 +551,18 @@ lun =simple_strtoul (p +1 , &p,0 ); err =scsi_remove_single_device (host, channel, id, lun); +if (err >=0 ) + err = length; + }else if (!strncmp ("rescan" , buffer +5 ,6 )) { + p = buffer +12 ; + + host =simple_strtoul (p, &p,0 ); + channel =simple_strtoul (p +1 , &p,0 ); + id =simple_strtoul (p +1 , &p,0 ); + lun =simple_strtoul (p +1 , &p,0 ); + err =scsi_rescan_single_device (host, channel, id, lun); +if (err >=0 ) + err = length; } out:
drivers/scsi/scsi_scan.c +18 -0
@@ -1796,6 +1796,24 @@return error; } +int scsi_rescan_single_device (uint host,uint channel,uint id,uint lun) +{ +struct scsi_device *sdev; +struct Scsi_Host *shost; + + shost =scsi_host_hn_get (host); +if (!shost) +return -ENODEV ; + sdev =scsi_find_device (shost, channel, id, lun); +if (!sdev) + goto out; + +scsi_rescan_device (sdev); +out: +scsi_host_put (shost); +return 0 ; +} +/** * scsi_scan_target - scan a target id, possibly including all LUNs on the * target.
drivers/scsi/sd.c +36 -1
@@ -93,10 +93,12 @@static int sd_attach (struct scsi_device *);static void sd_detach (struct scsi_device *); +static void sd_rescan (struct scsi_device *);static int sd_init_command (struct scsi_cmnd *);static int sd_synchronize_cache (struct scsi_disk *,int );static int sd_notifier (struct notifier_block *,unsigned long ,void *); - +static void sd_read_capacity (struct scsi_disk *sdkp,char *diskname, +struct scsi_request *SRpnt,unsigned char *buffer);static struct notifier_block sd_notifier_block = {sd_notifier,NULL ,0 };static struct Scsi_Device_Template sd_template = {
@@ -106,6 +108,7 @@ .scsi_type = TYPE_DISK, .attach = sd_attach, .detach = sd_detach, + .rescan = sd_rescan, .init_command = sd_init_command, .scsi_driverfs_driver = { .name = "sd",
@@ -627,6 +630,38 @@ not_present:set_media_not_present (sdkp);return 1 ; +} + +static void sd_rescan (struct scsi_device * sdp) +{ +unsigned char *buffer; +struct scsi_disk *sdkp =sd_find_by_sdev (sdp); +struct gendisk *gd; +struct scsi_request *SRpnt; + +if (!sdkp || sdp->online == FALSE || !sdkp->media_present) +return ; + + gd = sdkp->disk; + +SCSI_LOG_HLQUEUE (3 ,printk ("sd_rescan: disk=%s\n" , gd->disk_name)); + + SRpnt =scsi_allocate_request (sdp); +if (!SRpnt) { +printk (KERN_WARNING "(sd_rescan:) Request allocation " +"failure.\n" ); +return ; + } + +if (sdkp->device->host->unchecked_isa_dma) + buffer =kmalloc (512 ,GFP_DMA ); +else + buffer =kmalloc (512 ,GFP_KERNEL ); + +sd_read_capacity (sdkp, gd->disk_name, SRpnt, buffer); +set_capacity (gd, sdkp->capacity); +scsi_release_request (SRpnt); +kfree (buffer); }static int sd_revalidate_disk (struct gendisk *disk)
fs/block_dev.c +2 -0
@@ -623,6 +623,8 @@up (&whole->bd_sem); } }else { +if (!part) +bd_set_size (bdev,(loff_t )get_capacity (disk)<<9 );put_disk (disk);module_put (owner);if (bdev->bd_contains == bdev) {
drivers/scsi/scsi_proc.c line 565
Quoted 12 lines · Alex Tomas
drivers/scsi/scsi_proc.c +12
-0+if (err >=0 ) + err = length; + }else if (!strncmp ("rescan" , buffer +5 ,6 )) { + p = buffer +12 ; + + host =simple_strtoul (p, &p,0 ); + channel =simple_strtoul (p +1 , &p,0 ); + id =simple_strtoul (p +1 , &p,0 ); + lun =simple_strtoul (p +1 , &p,0 ); + err =scsi_rescan_single_device (host, channel, id, lun); +if (err >=0 ) + err = length;
Please don't add more procfs option. A resize attribute for the sysfs node of the scsi_device is the better choice in my opinion.
drivers/scsi/sd.c line 664
Quoted 8 lines
drivers/scsi/sd.c +8
-0+ buffer =kmalloc (512 ,GFP_DMA ); + else + buffer =kmalloc (512 ,GFP_KERNEL ); + +sd_read_capacity (sdkp, gd->disk_name, SRpnt, buffer); +set_capacity (gd, sdkp->capacity); +scsi_release_request (SRpnt); +kfree (buffer);
Don't you need some kind of serialization here?
fs/block_dev.c line 627
Quoted 8 lines
fs/block_dev.c +2
-0@@ -623,6 +623,8 @@up (&whole->bd_sem); } }else { +if (!part) +bd_set_size (bdev,(loff_t )get_capacity (disk)<<9 );
This needs more explanation.
Hi!
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Christoph Hellwig (CH) writes:
Quoted 6 lines · Alex Tomas
Quoted 6 lines
+ if (err >= 0) + err = length; + } else if (!strncmp("rescan", buffer + 5, 6)) { + p = buffer + 12; + + host =
simple_strtoul(p, &p, 0); + channel =simple_strtoul(p + 1, &p, 0); + id =simple_strtoul(p + 1, &p, 0); + lun =simple_strtoul(p + 1, &p, 0); + err =scsi_rescan_single_device(host, channel, id, lun); + if (err >= 0) + err = length;
CH> Please don't add more procfs option. A resize attribute for the CH> sysfs node of the scsi_device is the better choice in my opinion.
I like your idea.
Quoted 4 lines
Quoted 4 lines
+ buffer =
kmalloc(512, GFP_DMA); + else + buffer =kmalloc(512, GFP_KERNEL); + +sd_read_capacity(sdkp, gd->disk_name, SRpnt, buffer); +set_capacity(gd, sdkp->capacity); +scsi_release_request(SRpnt); + kfree(buffer);
CH> Don't you need some kind of serialization here?
Well. I think all changes sd_read_capacity() and set_capacity() make need not to be protected. Am I right?
Quoted 4 lines
Quoted 4 lines
---
linux/fs/block_dev.cMon Jan 20 02:23:49 2003 +++edited/fs/block_dev.cMon Mar 3 18:49:47 2003 @@ -623,6 +623,8 @@up(&whole->bd_sem); } } else { + if (!part) + bd_set_size(bdev,(loff_t)get_capacity(disk)<<9);
CH> This needs more explanation.
This is required because open("/dev/sd*",) should see new size of disk being used. James Bottomley suggested to introduce new ioctl, but I hope we may implmenent the feature w/o touching userspace tools.
with best regards, Alex
Hi!
Here is new version of the patch. All procfs-related stuff has been removed. One may rescan device size writing something to /sysfs/.../<scsi device>/rescan:
root@zefir:~# echo 1 >/sysfs/bus/scsi/devices/0\:0\:1\:0/rescan root@zefir:~# dmesg scsi0:A:1:0: Tagged Queuing enabled. Depth 64 scsi: host 0 channel 0 id 1 lun16384 has a LUN larger than allowed by the host adapter SCSI device sda: 2097152 512-byte hdwr sectors (1074 MB) SCSI device sda: drive cache: write through sda: unknown partition table Attached scsi disk sda at scsi0, channel 0, id 1, lun 0 SCSI device sda: 125829120 512-byte hdwr sectors (64425 MB) root@zefir:~#
drivers/scsi/hosts.h +1 -0
@@ -558,6 +558,7 @@void (*detach)(Scsi_Device *);int (*init_command)(Scsi_Cmnd *);/* Used by new queueing code. Selects command for blkdevs */ +void (*rescan)(Scsi_Device *);struct device_driver scsi_driverfs_driver; };
drivers/scsi/scsi.c +15 -0
@@ -1510,6 +1510,21 @@up_read (&scsi_devicelist_mutex); } +void scsi_rescan_device (struct scsi_device *sdev) +{ +struct Scsi_Device_Template *sdt; + +down_read (&scsi_devicelist_mutex); +list_for_each_entry (sdt, &scsi_devicelist, list) { +if (!try_module_get (sdt->module)) +continue ; +if (*sdt->rescan) + (*sdt->rescan)(sdev); +module_put (sdt->module); + } +up_read (&scsi_devicelist_mutex); +} +int scsi_device_get (struct scsi_device *sdev) {if (!try_module_get (sdev->host->hostt->module))
drivers/scsi/scsi_sysfs.c +20 -0
@@ -219,6 +219,25 @@sdev_rd_attr (rev,"%.4s\n" );sdev_rw_attr_bit (online); +static ssize_t +show_rescan_field (struct device *dev,char *buf) +{ +return 0 ; +} + +static ssize_t +store_rescan_field (struct device *dev,const char *buf,size_t count) +{ +int ret =ENODEV ; +struct scsi_device *sdev; + sdev =to_scsi_device (dev); +if (sdev) + ret =scsi_rescan_device (sdev); +return ret; +} + +static DEVICE_ATTR(rescan, S_IRUGO | S_IWUSR, show_rescan_field, store_rescan_field) + static struct device_attribute * const sdev_attrs[] = { &dev_attr_device_blocked, &dev_attr_queue_depth,
@@ -229,6 +248,7 @@ &dev_attr_model, &dev_attr_rev, &dev_attr_online, + &dev_attr_rescan, };/**
drivers/scsi/sd.c +36 -1
@@ -93,10 +93,12 @@static int sd_attach (struct scsi_device *);static void sd_detach (struct scsi_device *); +static void sd_rescan (struct scsi_device *);static int sd_init_command (struct scsi_cmnd *);static int sd_synchronize_cache (struct scsi_disk *,int );static int sd_notifier (struct notifier_block *,unsigned long ,void *); - +static void sd_read_capacity (struct scsi_disk *sdkp,char *diskname, +struct scsi_request *SRpnt,unsigned char *buffer);static struct notifier_block sd_notifier_block = {sd_notifier,NULL ,0 };static struct Scsi_Device_Template sd_template = {
@@ -106,6 +108,7 @@ .scsi_type = TYPE_DISK, .attach = sd_attach, .detach = sd_detach, + .rescan = sd_rescan, .init_command = sd_init_command, .scsi_driverfs_driver = { .name = "sd",
@@ -627,6 +630,38 @@ not_present:set_media_not_present (sdkp);return 1 ; +} + +static void sd_rescan (struct scsi_device * sdp) +{ +unsigned char *buffer; +struct scsi_disk *sdkp =sd_find_by_sdev (sdp); +struct gendisk *gd; +struct scsi_request *SRpnt; + +if (!sdkp || sdp->online == FALSE || !sdkp->media_present) +return ; + + gd = sdkp->disk; + +SCSI_LOG_HLQUEUE (3 ,printk ("sd_rescan: disk=%s\n" , gd->disk_name)); + + SRpnt =scsi_allocate_request (sdp); +if (!SRpnt) { +printk (KERN_WARNING "(sd_rescan:) Request allocation " +"failure.\n" ); +return ; + } + +if (sdkp->device->host->unchecked_isa_dma) + buffer =kmalloc (512 ,GFP_DMA ); +else + buffer =kmalloc (512 ,GFP_KERNEL ); + +sd_read_capacity (sdkp, gd->disk_name, SRpnt, buffer); +set_capacity (gd, sdkp->capacity); +scsi_release_request (SRpnt); +kfree (buffer); }static int sd_revalidate_disk (struct gendisk *disk)
fs/block_dev.c +3 -1
@@ -546,7 +546,7 @@return res; } -static void bd_set_size (struct block_device *bdev,loff_t size) +void bd_set_size (struct block_device *bdev,loff_t size) {unsigned bsize =bdev_hardsect_size (bdev); bdev->bd_inode->i_size = size;
@@ -623,6 +623,8 @@up (&whole->bd_sem); } }else { +if (!part) +bd_set_size (bdev,(loff_t )get_capacity (disk)<<9 );put_disk (disk);module_put (owner);if (bdev->bd_contains == bdev) {
Quoted 2 lines · On Tue, 2003-03-04 at 01:00, [email protected] wrote:
Here is new version of the patch. All procfs-related stuff has been removed. One may rescan device size writing something to /sysfs/.../<scsi device>/rescan:
I applied all of this, except this piece:
Quoted 6 lines
diff -uNr
linux/fs/block_dev.cedited/fs/block_dev.c
fs/block_dev.c line 630
Quoted 8 lines
fs/block_dev.c +2
-0@@ -623,6 +623,8 @@up (&whole->bd_sem); } }else { +if (!part) +bd_set_size (bdev,(loff_t )get_capacity (disk)<<9 );put_disk (disk);module_put (owner);if (bdev->bd_contains == bdev) {
Because adding this in will break the initial ramdisk. Thus, although the SCSI layer does resize, the block layer may not.
I've copied Al Viro because he's more familiar with the block layer device code than I and may have been planning to add this feature. Al, can you tell us what needs to happen to allow for hot resizing a SCSI disc?
Thanks,
James
Quoted 8 lines · James Bottomley
Quoted 8 lines
fs/block_dev.c +2
-0@@ -623,6 +623,8 @@up (&whole->bd_sem); } }else { +if (!part) +bd_set_size (bdev,(loff_t )get_capacity (disk)<<9 );
Quoted 8 lines
fs/block_dev.c line 630
Quoted 5 lines
fs/block_dev.c +0
-0put_disk (disk);module_put (owner);if (bdev->bd_contains == bdev) {Because adding this in will break the initial ramdisk. Thus, although the SCSI layer does resize, the block layer may not.
What about moving the size setting into ->open?
Quoted 27 lines · Alex Tomas
Hello!
Here is patch to implement hot scsi resize function. Modern storage boxes support virtualization feature and may change logical volume size online. I think it would be great if linux supports such abilities. Look at this example:
root@zefir:# dmesg | tail scsi0:A:1:0: Tagged Queuing enabled. Depth 32 SCSI device sda: 2097152 512-byte hdwr sectors (1074 MB) SCSI device sda: drive cache: write through sda: unknown partition table Attached scsi disk sda at scsi0, channel 0, id 1, lun 0root@zefir:# mount -treiserfs /dev/sda /mntroot@zefir:# df -Th Filesystem Type Size Used Avail Use% Mounted on /dev/hda1 ext3 1.9G 1.8G 138M 93% / /dev/sda reiserfs 1.0G 33M 991M 4% /mntroot@zefir:# echo 'scsi rescan 0 0 1 0' >/proc/scsi/scsi root@zefir:# dmesg|tail -n1 SCSI device sda: 20971520 512-byte hdwr sectors (10737 MB) root@zefir:# resize_reiserfs /dev/sda
Quoted 7 lines
<-------------resize_reiserfs, 2002-------------> reiserfsprogs 3.6.4
root@zefir:# df -Th Filesystem Type Size Used Avail Use% Mounted on /dev/hda1 ext3 1.9G 1.8G 138M 93% / /dev/sda reiserfs 10G 33M 9.9G 1% /mnt
Well, I also think it's a very important and needed feature for HA systems. I'm very interested in such things...
But, I thought resize_reiserfs only resize *unmounted* filesystem :
http://www.reiserfs.org/resize_reiserfs.html
Will it work under IO load ?
Reiserfs has a way to do it dynamically while using it, with mount option :
http://www.reiserfs.org/mount-options.html
I've tested this without a lot of success (I encounter a lot of problems).
I'm afraid that even if scsi subsystem support the resize option, FileSystems won't support it correctly...
Maybe with LVM ?
Did someone test it ?
Signature · 8 lines
Fabien SALVI Centre de Ressources Informatiques
Archamps, France -- http://www.cri74.org
PingOO GNU/linux distribution : http://www.pingoo.org
-
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.htmlQuoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Fabien Salvi (FS) writes:
FS> Well, I also think it's a very important and needed feature for FS> HA systems. I'm very interested in such things...
FS> But, I thought resize_reiserfs only resize *unmounted* filesystem FS> : http://www.reiserfs.org/resize_reiserfs.html
citate from this URL: "The resize_reiserfs program allows to grow a reiserfs on-line if there is a free space on block device."
FS> Will it work under IO load ?
I tested it several times under different load (read-only, write-only, read-write, single-thread and multi-thread tests). I think reiserfs team may give comments.
FS> Reiserfs has a way to do it dynamically while using it, with FS> mount option : http://www.reiserfs.org/mount-options.html
FS> I've tested this without a lot of success (I encounter a lot of FS> problems).
what kind of problem have you seen? what versions of kernel/reiserfs/tools?
FS> I'm afraid that even if scsi subsystem support the resize option, FS> FileSystems won't support it correctly... Maybe with LVM ?
FS> Did someone test it ?
Quoted 1 line
From filesystem point of view, LVM and resizable SCSI HDD are the same
think - just block device which may grow.
I think this patch is just one more step in the right direction.
Quoted 11 lines · [email protected] a écrit:
Quoted 2 lines
Quoted 2 lines
Quoted 2 lines
Quoted 2 lines
Quoted 1 line
Fabien Salvi (FS) writes:
FS> Well, I also think it's a very important and needed feature for FS> HA systems. I'm very interested in such things...
FS> But, I thought
resize_reiserfsonly resize *unmounted* filesystem FS> : http://www.reiserfs.org/resize_reiserfs.htmlcitate from this URL: "The
resize_reiserfsprogram allows to grow a reiserfs on-line if there is a free space on block device."
Yes, you're right !
I haven't seen this...
It's a bit strange, it contradicts what is said on the first line :)
Quoted 7 lines
FS> Will it work under IO load ?
I tested it several times under different load (read-only, write-only, read-write, single-thread and multi-thread tests). I think reiserfs team may give comments.
Quoted 7 lines
FS> Reiserfs has a way to do it dynamically while using it, with FS> mount option : http://www.reiserfs.org/mount-options.html
FS> I've tested this without a lot of success (I encounter a lot of FS> problems).
what kind of problem have you seen? what versions of
kernel/reiserfs/tools?
Well, I made some tests one year ago, I will try this again, as you say it seems to work well, it's interested...
I will let you know my new results.
Quoted 9 lines
FS> I'm afraid that even if scsi subsystem support the resize option, FS> FileSystems won't support it correctly... Maybe with LVM ?
FS> Did someone test it ?
Quoted 1 line
From filesystem point of view, LVM and resizable SCSI HDD are the same
think - just block device which may grow.
I think this patch is just one more step in the right direction.
Yes, surely !
Signature · 8 lines
Fabien SALVI Centre de Ressources Informatiques
Archamps, France -- http://www.cri74.org
PingOO GNU/linux distribution : http://www.pingoo.org
-
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html