ata_ram driver
I've ported the scsi_ram driver [1] to libata. It could use a lot more work -- there's a lot of stuff in the identify page that I haven't filled in, and there's a lot of commands it doesn't even try to execute.
For example, when you unload the driver, you get the mildly disturbing messages:
sd 12:0:0:0: [sdb] Stopping disk
sd 12:0:0:0: [sdb] START_STOP FAILED
sd 12:0:0:0: [sdb] Result: hostbyte=DID_BAD_TARGET driverbyte=DRIVER_OK,SUGGEST_OK
However, it's still useful at the current stage of development, so I thought it was worth posting to get some feedback.
[1] http://marc.info/?l=linux-scsi&m=120331663227540&w=2
drivers/ata/Kconfig +3 -0
@@ -40,6 +40,9 @@ config ATA_ACPI You can disable this at kernel boot time by using the option libata.noacpi=1 +config ATA_RAM + tristate "ATA RAM driver" + config SATA_AHCI tristate "AHCI SATA support" depends on PCI
drivers/ata/Makefile +3 -0
@@ -77,6 +77,9 @@ obj-$(CONFIG_ATA_GENERIC) += ata_generic.o # Should be last libata driver obj-$(CONFIG_PATA_LEGACY) += pata_legacy.o +# A fake ata driver. Can it be postultimate? +obj-$(CONFIG_ATA_RAM) += ata_ram.o + libata-objs := libata-core.o libata-scsi.o libata-sff.o libata-eh.o \ libata-pmp.o libata-$(CONFIG_ATA_ACPI) += libata-acpi.o
drivers/ata/ata_ram.c new file +674 -0
674 lines not on this page · raw message
Signature · 4 lines
Intel are signing my paycheques ... these opinions are still mine "Bill, look, we understand that you're interested in selling us this operating system, but compare it to ours. We can't possibly take such a retrograde step."
Quoted 11 lines · Matthew Wilcox
I've ported the
scsi_ramdriver [1] to libata. It could use a lot more work -- there's a lot of stuff in the identify page that I haven't filled in, and there's a lot of commands it doesn't even try to execute.For example, when you unload the driver, you get the mildly disturbing messages:
sd 12:0:0:0: [sdb] Stopping disk
sd 12:0:0:0: [sdb]START_STOPFAILED
sd 12:0:0:0: [sdb] Result: hostbyte=DID_BAD_TARGET driverbyte=DRIVER_OK,SUGGEST_OK
..
I see messages like those with *established* libata drivers from time to time. It could just be a bug in the shutdown sequence, somewhere between libata, SCSI, block layer, and the device model in general. Or not.
Cheers
Quoted 13 lines · Mark Lord
Quoted 4 lines · Matthew Wilcox
I've ported the
scsi_ramdriver [1] to libata. It could use a lot more work -- there's a lot of stuff in the identify page that I haven't filled in, and there's a lot of commands it doesn't even try to execute.Quoted 8 lines
For example, when you unload the driver, you get the mildly disturbing messages:
sd 12:0:0:0: [sdb] Stopping disk
sd 12:0:0:0: [sdb]START_STOPFAILED
sd 12:0:0:0: [sdb] Result: hostbyte=DID_BAD_TARGET driverbyte=DRIVER_OK,SUGGEST_OK
Quoted 6 lines
..
I see messages like those with *established* libata drivers from time to time.
It could just be a bug in the shutdown sequence, somewhere between libata, SCSI, block layer, and the device model in general. Or not.
It's because of the sequence of events. Currently, driver unload sequence is the same as when the device is hot unplugged. libata detects that the device is gone and disables it and report it to SCSI layer. SCSI layer takes over and tries to kill the SCSI device and tell sd to shutdown and sd issues START_STOP to shutdown which fails w/ DID_BAD_TARGET because the matching ATA device is already gone. I've left it that way because I'm not sure whether spinning down the drive on driver unload is the correct thing to do. The message is annoying tho.
Thanks.
Signature · 1 line
tejun
James Bottomley
maintainerQuoted 21 lines · Tejun Heo
Quoted 13 lines · Mark Lord
Quoted 4 lines · Matthew Wilcox
I've ported the
scsi_ramdriver [1] to libata. It could use a lot more work -- there's a lot of stuff in the identify page that I haven't filled in, and there's a lot of commands it doesn't even try to execute.Quoted 8 lines
For example, when you unload the driver, you get the mildly disturbing messages:
sd 12:0:0:0: [sdb] Stopping disk
sd 12:0:0:0: [sdb]START_STOPFAILED
sd 12:0:0:0: [sdb] Result: hostbyte=DID_BAD_TARGET driverbyte=DRIVER_OK,SUGGEST_OKQuoted 6 lines
..
I see messages like those with *established* libata drivers from time to time.
It could just be a bug in the shutdown sequence, somewhere between libata, SCSI, block layer, and the device model in general. Or not.
Quoted 8 lines
It's because of the sequence of events. Currently, driver unload sequence is the same as when the device is hot unplugged. libata detects that the device is gone and disables it and report it to SCSI layer. SCSI layer takes over and tries to kill the SCSI device and tell sd to shutdown and sd issues
START_STOPto shutdown which fails w/DID_BAD_TARGETbecause the matching ATA device is already gone. I've left it that way because I'm not sure whether spinning down the drive on driver unload is the correct thing to do. The message is annoying tho.
Um, it's not supposed to happen that way. Your signal that a disk is gone is slave destroy ... and we don't call that until after the target has been processed. Devices are supposed to stay online (if possible) from slave alloc to slave destroy.
James
Quoted 9 lines · James Bottomley
Quoted 8 lines
It's because of the sequence of events. Currently, driver unload sequence is the same as when the device is hot unplugged. libata detects that the device is gone and disables it and report it to SCSI layer. SCSI layer takes over and tries to kill the SCSI device and tell sd to shutdown and sd issues
START_STOPto shutdown which fails w/DID_BAD_TARGETbecause the matching ATA device is already gone. I've left it that way because I'm not sure whether spinning down the drive on driver unload is the correct thing to do. The message is annoying tho.
Quoted 4 lines
Um, it's not supposed to happen that way. Your signal that a disk is gone is slave destroy ... and we don't call that until after the target has been processed. Devices are supposed to stay online (if possible) from slave alloc to slave destroy.
Currently, it's like the following.
* Explicit unplug request via sysfs or whatever: ATA device stays online till slave_destroy finishes.
* Hot unplugging: Nothing much libata can do. ATA device is yanked out by the user.
* Driver unload: Dealt the same way as hot unplugging.
Making driver unload like explicit unplug request is possible but it will mean that drives will be spun down on driver unload, which can be annoying to developers. In addition, the code path is shared with controller hot unplug in which case it's probably best not to issue any new command. So, I've been reluctant to make the change. If the change is required, I think it can be done by adding a few lines at the top of ata_port_detach(). Jeff, what do you think?
Signature · 1 line
tejun
James Bottomley
maintainerQuoted 15 lines · Tejun Heo
Quoted 9 lines · James Bottomley
Quoted 8 lines
It's because of the sequence of events. Currently, driver unload sequence is the same as when the device is hot unplugged. libata detects that the device is gone and disables it and report it to SCSI layer. SCSI layer takes over and tries to kill the SCSI device and tell sd to shutdown and sd issues
START_STOPto shutdown which fails w/DID_BAD_TARGETbecause the matching ATA device is already gone. I've left it that way because I'm not sure whether spinning down the drive on driver unload is the correct thing to do. The message is annoying tho.Quoted 4 lines
Um, it's not supposed to happen that way. Your signal that a disk is gone is slave destroy ... and we don't call that until after the target has been processed. Devices are supposed to stay online (if possible) from slave alloc to slave destroy.
Quoted 4 lines
Currently, it's like the following.
* Explicit unplug request via sysfs or whatever: ATA device stays online till
slave_destroyfinishes.
That's correct
Quoted 2 lines
* Hot unplugging: Nothing much libata can do. ATA device is yanked out by the user.
Yes, us too ... you just have to error all commands when the device vanishes.
Quoted 1 line
* Driver unload: Dealt the same way as hot unplugging.
This is the problem case: driver unloading should have a scsi_remove_host() in its path. This is the trigger that sends out the flushes/stops and calls slave_destroy. scsi_remove_host() doesn't actually return until all the destroys are completed, so it makes module unloading wait until everything is properly shut down.
Quoted 3 lines
Making driver unload like explicit unplug request is possible but it will mean that drives will be spun down on driver unload, which can be annoying to developers.
You have a sysfs flag to prevent that, don't you?
Quoted 5 lines
In addition, the code path is shared with
controller hot unplug in which case it's probably best not to issue any new command. So, I've been reluctant to make the change. If the change is required, I think it can be done by adding a few lines at the top ofata_port_detach(). Jeff, what do you think?
James
Quoted 8 lines · James Bottomley
Quoted 1 line
* Driver unload: Dealt the same way as hot unplugging.
This is the problem case: driver unloading should have a
scsi_remove_host()in its path. This is the trigger that sends out the flushes/stops and callsslave_destroy.scsi_remove_host()doesn't actually return until all the destroys are completed, so it makes module unloading wait until everything is properly shut down.
Quoted 5 lines
Quoted 3 lines
Making driver unload like explicit unplug request is possible but it will mean that drives will be spun down on driver unload, which can be annoying to developers.
You have a sysfs flag to prevent that, don't you?
Yeap, sure. It's the combination of things that always made me put this off. Is there a function I can call to just shutdown the host instead of destroying it?
Thanks.
Signature · 1 line
tejun
James Bottomley
maintainerQuoted 13 lines · Tejun Heo
Quoted 12 lines · James Bottomley
Quoted 1 line
* Driver unload: Dealt the same way as hot unplugging.
This is the problem case: driver unloading should have a
scsi_remove_host()in its path. This is the trigger that sends out the flushes/stops and callsslave_destroy.scsi_remove_host()doesn't actually return until all the destroys are completed, so it makes module unloading wait until everything is properly shut down.Quoted 3 lines
Making driver unload like explicit unplug request is possible but it will mean that drives will be spun down on driver unload, which can be annoying to developers.
Quoted 5 lines
Quoted 1 line
You have a sysfs flag to prevent that, don't you?
Yeap, sure. It's the combination of things that always made me put this off. Is there a function I can call to just shutdown the host instead of destroying it?
Not really ... the process of unbinding the ULDs causes their remove methods to call shudown. It is possible to separate this in the ULDS; but the original design was to make remove and shutdown be similar for the very reason that if you're removing the driver with unflushed data in the cache, we'd really like it flushed (flush is called from shutdown) because you have no way to talk to the device after this without reinserting the driver.
James
Quoted 11 lines · James Bottomley
Quoted 3 lines
Yeap, sure. It's the combination of things that always made me put this off. Is there a function I can call to just shutdown the host instead of destroying it?
Not really ... the process of unbinding the ULDs causes their remove methods to call shudown. It is possible to separate this in the ULDS; but the original design was to make remove and shutdown be similar for the very reason that if you're removing the driver with unflushed data in the cache, we'd really like it flushed (flush is called from shutdown) because you have no way to talk to the device after this without reinserting the driver.
The problem is that libata EH and other stuff aren't ready to let go of the SCSI host up until the last moment and that last moment can't be moved before SCSI host destruction because shutdown sequence (flush and spindown) requires live EH. I think this can be solved by shooting down individual sdev's instead of destroying the scsi_host.
Thanks.
Signature · 1 line
tejun
James Bottomley
maintainerQuoted 13 lines · Tejun Heo
Quoted 11 lines · James Bottomley
Quoted 3 lines
Yeap, sure. It's the combination of things that always made me put this off. Is there a function I can call to just shutdown the host instead of destroying it?
Not really ... the process of unbinding the ULDs causes their remove methods to call shudown. It is possible to separate this in the ULDS; but the original design was to make remove and shutdown be similar for the very reason that if you're removing the driver with unflushed data in the cache, we'd really like it flushed (flush is called from shutdown) because you have no way to talk to the device after this without reinserting the driver.
Quoted 5 lines
The problem is that libata EH and other stuff aren't ready to let go of the SCSI host up until the last moment and that last moment can't be moved before SCSI host destruction because shutdown sequence (flush and spindown) requires live EH. I think this can be solved by shooting down individual sdev's instead of destroying the
scsi_host.
Basically what scsi_scan.c:scsi_forget_host() does? It's used internally at the moment, but I suppose we could export it.
James
Quoted 12 lines · James Bottomley
Quoted 11 lines · Tejun Heo
Quoted 10 lines · James Bottomley
Quoted 3 lines
Yeap, sure. It's the combination of things that always made me put this off. Is there a function I can call to just shutdown the host instead of destroying it?
Not really ... the process of unbinding the ULDs causes their remove methods to call shudown. It is possible to separate this in the ULDS; but the original design was to make remove and shutdown be similar for the very reason that if you're removing the driver with unflushed data in the cache, we'd really like it flushed (flush is called from shutdown) because you have no way to talk to the device after this without reinserting the driver.
Quoted 8 lines
Quoted 5 lines
The problem is that libata EH and other stuff aren't ready to let go of the SCSI host up until the last moment and that last moment can't be moved before SCSI host destruction because shutdown sequence (flush and spindown) requires live EH. I think this can be solved by shooting down individual sdev's instead of destroying the
scsi_host.Basically what scsi_scan.c:scsi_forget_host() does? It's used internally at the moment, but I suppose we could export it.
Yeap, exactly. I'll prep a patch after breakfast.
Signature · 1 line
tejun
PATCH 1/2 scsi: export scsi_forget_host()
Export scsi_forget_host(), will be used by libata.
--- drivers/scsi/scsi_priv.h | 1 - drivers/scsi/scsi_scan.c | 1 + include/scsi/scsi_host.h | 1 + 3 files changed, 2 insertions(+), 1 deletion(-)
drivers/scsi/scsi_priv.h +0 -1
@@ -98,7 +98,6 @@ extern void scsi_exit_procfs(void);/* scsi_scan.c */ extern int scsi_scan_host_selected (struct Scsi_Host *,unsigned int ,unsigned int ,unsigned int ,int ); -extern void scsi_forget_host (struct Scsi_Host *);extern void scsi_rescan_device (struct device *);/* scsi_sysctl.c */
drivers/scsi/scsi_scan.c +1 -0
@@ -1845,6 +1845,7 @@ void scsi_forget_host(struct Scsi_Host * }spin_unlock_irqrestore (shost->host_lock, flags); } +EXPORT_SYMBOL (scsi_forget_host);/* * Function: scsi_get_host_dev()
include/scsi/scsi_host.h +1 -0
@@ -719,6 +719,7 @@ extern struct Scsi_Host *scsi_host_allocextern int __must_check scsi_add_host (struct Scsi_Host *,struct device *);extern void scsi_scan_host (struct Scsi_Host *);extern void scsi_rescan_device (struct device *); +extern void scsi_forget_host (struct Scsi_Host *);extern void scsi_remove_host (struct Scsi_Host *);extern struct Scsi_Host *scsi_host_get (struct Scsi_Host *);extern void scsi_host_put (struct Scsi_Host *t);
PATCH 2/2 libata: kill SCSI devices before detaching ata_host
Kill SCSI devices before detaching port. This makes drives properly shut down on driver unload.
--- drivers/ata/libata-core.c | 8 ++++++++ 1 file changed, 8 insertions(+)
drivers/ata/libata-core.c +8 -0
@@ -7236,6 +7236,14 @@ static void ata_port_detach(struct ata_pif (!ap->ops->error_handler) goto skip_eh; +/* First, tell all SCSI devices that we're going down. Note +* that there's a small race window here. Devices which get +* hotplugged after forget_host but before EH is killed won't +* get shut down by SCSI layer properly and will miss cache +* flush and spin down. +*/ +scsi_forget_host (ap->scsi_host); +/* tell EH we're leaving & flush EH */ spin_lock_irqsave (ap->lock, flags); ap->pflags |=ATA_PFLAG_UNLOADING ;
Quoted 12 lines · Tejun Heo
Quoted 10 lines · James Bottomley
Quoted 3 lines
Yeap, sure. It's the combination of things that always made me put this off. Is there a function I can call to just shutdown the host instead of destroying it?
Not really ... the process of unbinding the ULDs causes their remove methods to call shudown. It is possible to separate this in the ULDS; but the original design was to make remove and shutdown be similar for the very reason that if you're removing the driver with unflushed data in the cache, we'd really like it flushed (flush is called from shutdown) because you have no way to talk to the device after this without reinserting the driver.
Quoted 5 lines
The problem is that libata EH and other stuff aren't ready to let go of the SCSI host up until the last moment and that last moment can't be moved before SCSI host destruction because shutdown sequence (flush and spindown) requires live EH. I think this can be solved by shooting down individual sdev's instead of destroying the
scsi_host.
I'm curious how the picture would change, if we used a scsi_host for each ata_host.
Jeff
James Bottomley
maintainerQuoted 13 lines · Jeff Garzik
Quoted 12 lines · Tejun Heo
Quoted 10 lines · James Bottomley
Quoted 3 lines
Yeap, sure. It's the combination of things that always made me put this off. Is there a function I can call to just shutdown the host instead of destroying it?
Not really ... the process of unbinding the ULDs causes their remove methods to call shudown. It is possible to separate this in the ULDS; but the original design was to make remove and shutdown be similar for the very reason that if you're removing the driver with unflushed data in the cache, we'd really like it flushed (flush is called from shutdown) because you have no way to talk to the device after this without reinserting the driver.
Quoted 8 lines
Quoted 5 lines
The problem is that libata EH and other stuff aren't ready to let go of the SCSI host up until the last moment and that last moment can't be moved before SCSI host destruction because shutdown sequence (flush and spindown) requires live EH. I think this can be solved by shooting down individual sdev's instead of destroying the
scsi_host.I'm curious how the picture would change, if we used a
scsi_hostfor eachata_host.
It would probably make the whole paradigm a lot easier. Currently, if you look at the transport classes that do this type of thing, they shadow host and add port and other components as extra bits. libata does a rather strange thing trying to have one SCSI host per SATA port, so scsi_host and ata_host don't match up. Then on destruction you can just follow the standard SCSI teardown path.
James