simple scsi device mapper module

Dmitry Filippov filippovd20 at gmail.com
Wed Oct 17 10:57:20 EDT 2012


Hi,

Recently i've started with development of kernel module, which uses
existing block devices/partitions as backend and represents itself as
scsi disk.

i've found good start point - scsi_debug module which is in official
kernel tree under drivers/scsi/
i suppose you are aware about this module. So in fact it is low level
scsi adapter which represents itself as scsi disk /dev/sd? on the
system and uses RAM as backend storage. actually what i need!

so my general idea was to use this it as base and do some changes in IO.

scsi_debug IO is trivial. It allocates memory by vmalloc() in __init
to fake_storep pointer.
and then use it in IO.

but the problem appeared for me to rewrite these places of fake_storep
usage to write/read to existing block device.

i've investigated of how device mapper achieve this. - by generic
block layer. the key tool is submit_bio(). Well, submit_bio is not
difficult and i was able to read and write bios to/from block device.

How writing is done in scsi_debug:
scsi_debug has   .queuecommand = scsi_debug_queuecommand which switch
scsi command to READ/WRITE_6/10/12/16/32
and calls  resp_read/write() they both call do_device_access() and it
in turn fetch_to_dev_buffer or fill_from_dev_buffer if read or write
required.
both them use scsi_sg_copy_to_buffer or sg_copy_from_buffer... so
these functions eventually fetch/fill scsi response buffer
from existing fake RAM storage.

all seems to be fine and clear before trying to replace RAM storage by
real block device.
the problem is that then we are in  scsi_debug_queuecommand we can not
block(sleep).
any attempt to call function that may block causes oops. or even hang.
with BUG: sleeping function called from invalid context
because of upstream scsi layers holds locks while handling request as
for example scsi_dispatch_cmd from drivers/scsi/scsi.c:
...
spin_lock_irqsave(host->host_lock, flags);
...

in case of scsi WRITE command i have workaround. i can simply allocate
some temporary buffer with GFP_ATOMIC to handle write request (its max
size 512K - scsi mid layer breaks request to low level adapter in
these chunks).
pass this buffer to scsi_sg_copy_to_buffer - it will fill my temporary
buffer without blocking. then setup workqueue work and actual
submit_bio() to block device will be handled later from thread context
where such operations are normal.

the problem is with response to READ.
scsi_debug just uses sg_copy_from_buffer from RAM storage - where data
is always uptodate.
but in my case i need to read data from block device by submit_bio
first and only after this can use buffer updated to pass it to
sg_copy_from_buffer... I still don't have idea how to accomplish this.

does anyone have any idea?

thank you in advance for any suggestions or criticism.

thanks,
Dmitry



More information about the Kernelnewbies mailing list