]> git.hungrycats.org Git - linux/commitdiff
[PATCH] Re: hot scsi disk resize
authorAlex Tomas <alexey@technomagesinc.com>
Fri, 14 Mar 2003 12:43:43 +0000 (06:43 -0600)
committerJames Bottomley <jejb@raven.il.steeleye.com>
Fri, 14 Mar 2003 12:43:43 +0000 (06:43 -0600)
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
drivers/scsi/scsi.c
drivers/scsi/scsi_sysfs.c
drivers/scsi/sd.c
fs/block_dev.c

index c8098010e86b839a2de835a92c36ee99f54821c1..f5f428711b3489927a143a1f77c292814a5231fc 100644 (file)
@@ -549,6 +549,7 @@ struct Scsi_Device_Template
     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;
 };
 
index 0cbfd0c762bbdb89ddf572ab69fe38cda8e98ecc..78577c1818846f9311ae6131cd7e8f8d74c23592 100644 (file)
@@ -1264,6 +1264,21 @@ void scsi_detach_device(struct scsi_device *sdev)
        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))
index eade9fd9b026d39a69feba08ca6eed974ae802a6..4ecaa390ebdcb59750687b5e8297735c253e7e70 100644 (file)
@@ -266,6 +266,25 @@ sdev_rd_attr (model, "%.16s\n");
 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,
@@ -276,6 +295,7 @@ static struct device_attribute * const sdev_attrs[] = {
        &dev_attr_model,
        &dev_attr_rev,
        &dev_attr_online,
+       &dev_attr_rescan,
 };
 
 /**
index 12d4a683963966c8c7b8fdc14d41dc345d0a38ee..eadc8315551a4584709652e758f91aff1de13bb9 100644 (file)
@@ -93,10 +93,12 @@ static void sd_rw_intr(struct scsi_cmnd * SCpnt);
 
 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 @@ static struct Scsi_Device_Template sd_template = {
        .scsi_type      = TYPE_DISK,
        .attach         = sd_attach,
        .detach         = sd_detach,
+       .rescan         = sd_rescan,
        .init_command   = sd_init_command,
        .scsi_driverfs_driver = {
                .name   = "sd",
@@ -629,6 +632,38 @@ not_present:
        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)
 {
        struct scsi_disk *sdkp = scsi_disk(disk);
index d46f44fb0d47b011548b9ebf83fb2f7a12b86697..b3dc2d6e0aa622d8319d3ea512c5a9636a8460f2 100644 (file)
@@ -573,6 +573,8 @@ static int do_open(struct block_device *bdev, struct inode *inode, struct file *
                        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) {