Linux specific scsi CDBs vs REQ_TYPE_LINUX_BLOCK requests
Hi Jens,
way back you introduced REQ_TYPE_LINUX_BLOCK requests as some sort of generic block layer messages. As it turns out, it is not quite obvious how to add support for this type of requests in the scsi subsystem properly. On the other hand, Boaz Harrosh has recently added support for variable length and in particular vendor specific CDBs to the scsi mid layer. My question to you and James is this: Would it make sense, in your opinion, to (ab)use BLOCK_PC requests carrying linux specific CDBs for those purposes you had in mind when introducing LINUX_BLOCK requests? This would make things much easier as far as scsi is concerned and it would still be possible to add suport for this kind of requests to non scsi drivers. On the other hand, this might constitute too serious a violation of the layers and subsystems involved as I'm not quite sure, for instance, where to keep the list of those linux specific opcodes -- include/linux/blkdev.h and include/scsi/scsi.h both don't seem quite right.
The reason why I'm bothering you with all this is that I'm trying to get disk shock protection merged into mainline eventually; see the subthread starting at [1] for a preliminary patch series. Since I want to make this feature available to both, libata as well as ide, it is appealing to put the common bits (the timer and the user interface) into the block layer, thus avoiding code duplication. However, given the difficulties to realise this approach sanely, it might be better to leave the block layer out of it as far as possible. After all, it's the ATA specific feature (immediate disk head unloading) I really care for and by means of ioctls we could still provide an interface to userspace which doesn't depend on whether the device is managed by libata or ide.
In fact, unless you are definitely in favour of the block layer approach (as realised in [2]) and can give me a hint as to how I could solve the problems described above, I will probably prepare a patch series using ioctls and post it on linux-ide. The reason is that this approach might even solve another problem I see further down the road.
Thank you for your advice,
Elias
[1] <http://permalink.gmane.org/gmane.linux.ide/29519>
[2] <http://permalink.gmane.org/gmane.linux.ide/29523>
Quoted 17 lines · Elias Oltmanns
Hi Jens,
way back you introduced
REQ_TYPE_LINUX_BLOCKrequests as some sort of generic block layer messages. As it turns out, it is not quite obvious how to add support for this type of requests in the scsi subsystem properly. On the other hand, Boaz Harrosh has recently added support for variable length and in particular vendor specific CDBs to the scsi mid layer. My question to you and James is this: Would it make sense, in your opinion, to (ab)useBLOCK_PCrequests carrying linux specific CDBs for those purposes you had in mind when introducingLINUX_BLOCKrequests? This would make things much easier as far as scsi is concerned and it would still be possible to add suport for this kind of requests to non scsi drivers. On the other hand, this might constitute too serious a violation of the layers and subsystems involved as I'm not quite sure, for instance, where to keep the list of those linux specific opcodes --include/linux/blkdev.handinclude/scsi/scsi.hboth don't seem quite right.
Large cdb support is just a direct extension of REQ_BLOCK_PC as far as I'm concerned, it doesn't fit well with the REQ_TYPE_LINUX_BLOCK.
Quoted 11 lines
The reason why I'm bothering you with all this is that I'm trying to get disk shock protection merged into mainline eventually; see the subthread starting at [1] for a preliminary patch series. Since I want to make this feature available to both, libata as well as ide, it is appealing to put the common bits (the timer and the user interface) into the block layer, thus avoiding code duplication. However, given the difficulties to realise this approach sanely, it might be better to leave the block layer out of it as far as possible. After all, it's the ATA specific feature (immediate disk head unloading) I really care for and by means of ioctls we could still provide an interface to userspace which doesn't depend on whether the device is managed by libata or ide.
So wrt opcodes, the space from 0x40 and up should be generic Linux sanctioned opcodes. For the disk shock protection, you would like something like REQ_LB_OP_PARKHEAD?
Quoted 5 lines
In fact, unless you are definitely in favour of the block layer approach (as realised in [2]) and can give me a hint as to how I could solve the problems described above, I will probably prepare a patch series using ioctls and post it on linux-ide. The reason is that this approach might even solve another problem I see further down the road.
There isn't going to be a lot of common code, since all the park handling will be driver/device specific. It still makes sense to use the queue as the transport for the command though, using an ioctl is both ugly from a design POV and (more importantly) has serialization issues since it's an out-of-band signalling mechanism. If you pass down a request as the park request, then you need only deal with the device specific details of parking the head.
Signature · 1 line
Jens Axboe
Quoted 1 line · Jens Axboe
On Thu, May 08 2008, Elias Oltmanns wrote:
[...]
Quoted 8 lines
Quoted 5 lines
In fact, unless you are definitely in favour of the block layer approach (as realised in [2]) and can give me a hint as to how I could solve the problems described above, I will probably prepare a patch series using ioctls and post it on linux-ide. The reason is that this approach might even solve another problem I see further down the road.
There isn't going to be a lot of common code, since all the park handling will be driver/device specific.
Yes, it's just the expiration timer and possibly the interface to user space that could be considered common code.
Quoted 6 lines
It still makes sense to use the queue as the transport for the command though, using an ioctl is both ugly from a design POV and (more importantly) has serialization issues since it's an out-of-band signalling mechanism. If you pass down a request as the park request, then you need only deal with the device specific details of parking the head.
Well, the request queue is certainly the most obvious and preferable way to solve these serialisation issues -- the only drawback being that other paths might involve less memory allocations, thus reducing potential issues with paging in when time is of the essence. The question remains, however, who should be responsible for enqueueing such a request? And if it is going to be a REQ_TYPE_LINUX_BLOCK request, how am I supposed to get it past scsi midlayer to the LLDD? But I'll discuss that particular issue in a seperate mail.
Here is another aspect which I'd like to have your opinion as maintainer of the block layer about. The more I think about it, the more I am opposed to the idea to expose a generic queue freezing facility to user space for *all* block devices. Or rather, I don't consider disk shock protection an extension, as it were, of such a generic facility. The reason is simply that I don't see how the two concepts can be generally compatible. If queue freezing was sufficient for any given application and for any given block device, then we'd most likely want to freeze the queue of ATA devices just as we'd do for other devices, i.e., without disk head unloading. This is because the number of head unloads is considered an indicator of disk aging.
So, I'd like to export an interface to user space which is specifically dedicated to disk shock protection, i.e., only available for ATA / IDE devices. On the other hand, it would be desirable to make this interface transparent, so user space doesn't have to differentiate between devices driven by the libata or the ide subsystem. A sysfs attribute /sys/block/.../queue/protect or even just /sys/block/.../protect would be very convenient from a user's point of view. However, this would require something like a blk_register_protect_attr() / blk_unregister_protect_attr() interface so that libata and ide can export this attribute for disks after calling blk_init_queue(). Would that be alright with you? Otherwise, I'd have to implement this interface directly in the subsystems and *thats* where ioctls seem to be the easiest way to make this interface as transparent as possible to user space. In this case a park request of some sort would be fed to the request queue internally.
Any comments?
Elias
Quoted 1 line · Elias Oltmanns
Jens Axboe <[email protected]> wrote:
[...]
Quoted 7 lines
Quoted 6 lines
It still makes sense to use the queue as the transport for the command though, using an ioctl is both ugly from a design POV and (more importantly) has serialization issues since it's an out-of-band signalling mechanism. If you pass down a request as the park request, then you need only deal with the device specific details of parking the head.
Quoted 8 lines
Well, the request queue is certainly the most obvious and preferable way to solve these serialisation issues -- the only drawback being that other paths might involve less memory allocations, thus reducing potential issues with paging in when time is of the essence. The question remains, however, who should be responsible for enqueueing such a request? And if it is going to be a
REQ_TYPE_LINUX_BLOCKrequest, how am I supposed to get it past scsi midlayer to the LLDD? But I'll discuss that particular issue in a seperate mail.
Right, this is something for the scsi people and probably James in particular to comment on. Earlier this year, I sent a patch [1] to implement REQ_TYPE_LINUX_BLOCK in the scsi subsystem. Maybe, an alternative approach would be to set aside a linux specific scsi opcode (courtesy of Boaz's variable length cdb support) in order to attach LINUX_BLOCK requests to this cdb and hand them down to LLDDs. However, I'm not quite sure whether this is feasible or, indeed, desirable in the long run.
And finally, here is yet another, but I'm afraid just as hackish possibility to get shock protection working for both libata and ide: We define linux specific opcodes for the park and resume commands in addition to the REQ_TYPE_LINUX_BLOCK opcodes. This way, we have to options:
1. The block layer provides the interface to request immediate disk head unloading and enqueues appropriate LINUX_BLOCK requests accordingly. ide is modified to handle these requests directly, whereas scsi ULD or midlayer translates them to the corresponding linux specific cdb.
2. The subsystem (i.e., ide / libata) exposes the interface to request head unloading and queues up a park or resume request as directed. ide would enqueue a LINUX_BLOCK request, whereas libata could stick to BLOCK_PC requests by means of the linux specific cdbs for that purpose.
So, which way am I to turn here?
[...]
Quoted 7 lines
So, I'd like to export an interface to user space which is specifically dedicated to disk shock protection, i.e., only available for ATA / IDE devices. On the other hand, it would be desirable to make this interface transparent, so user space doesn't have to differentiate between devices driven by the libata or the ide subsystem. A sysfs attribute
/sys/block/.../queue/protector even just/sys/block/.../protectwould be very convenient from a user's point of view. However, this would
Quoted 8 lines
require something like a
blk_register_protect_attr()/blk_unregister_protect_attr()interface so that libata and ide can export this attribute for disks after callingblk_init_queue(). Would that be alright with you? Otherwise, I'd have to implement this interface directly in the subsystems and *thats* where ioctls seem to be the easiest way to make this interface as transparent as possible to user space. In this case a park request of some sort would be fed to the request queue internally.
Alternatively, we could have similar scsi_register_protect_attr() and scsi_unregister_protect_attr() functions to be called from libata's ->slave_configure() callback. Not sure whether that's any better.
Regards,
Elias