* simple block device - request processing in threads
@ 2017-03-03 10:12 Andras Pal
2017-03-04 13:52 ` Pranay Srivastava
0 siblings, 1 reply; 3+ messages in thread
From: Andras Pal @ 2017-03-03 10:12 UTC (permalink / raw)
To: kernelnewbies
Dear All,
with some experience in low-level C programming, I started to develop a
kernel module which allows I2C slave EEPROM-alike devices (EEPROMs, FRAMs,
BBRAMs, etc) to be accessed as block devices. Since the i/o transactions are
relatively slow (say, 40k/sec), i'm using kernel threads. However, it seems
that while the read (rq_data_dir(req)) == 0) operations are fine, write
operations (rq_data_dir != 0) seems to be lost. For instance, if I do `dd
bs=512 count=32 of=/dev/i2cblk0`, only the first 8 sectors are fetched by
blk_fetch_request(). I copy the critical/relevant/interesting parts after this
message. The code is based on drivers/block/nbd.c.
In addition - according to printk()-based debugging - after each write request,
the kernel starts to access sectors in the order of 0, 24, 8, 56, 120, 64, 32
(with 8 sectors == 1 page per request). Maybe it seeks for some filesystems...?
Can this feature be turned off (like setting
disk->queue->backing_dev_info.ra_pages to zero in order to turn off
readaheaad)?
thanks in advance, cheers, Andras
/*****************************************************************************/
static int i2cblk_process_io_request(struct i2cblk_device *device,struct request *req)
{
int ret;
/* i2cblk_transfer(): this function calls i2c_master_send/recv(), etc. */
ret=i2cblk_transfer(device, blk_rq_pos(req), blk_rq_cur_sectors(req),
bio_data(req->bio),
rq_data_dir(req));
return(ret);
}
static void i2cblk_request(struct request_queue *q)
{
struct request *req;
while ( (req=blk_fetch_request(q)) != NULL )
{ struct i2cblk_device *device;
if ( req->cmd_type != REQ_TYPE_FS )
{ __blk_end_request_all(req, -EIO);
continue;
}
/* spin_unlock_irq(q->queue_lock); */
device=req->rq_disk->private_data;
spin_lock_irq(&device->active_lock);
list_add_tail(&req->queuelist,&device->active_queue);
spin_unlock_irq(&device->active_lock);
wake_up(&device->active_wq);
/* spin_lock_irq(q->queue_lock); */
};
}
static void i2cblk_end_request(struct request *req)
{
int error;
struct request_queue *q = req->q;
unsigned long flags;
error=(req->errors ? -EIO : 0);
spin_lock_irqsave(q->queue_lock, flags);
__blk_end_request_all(req, error);
spin_unlock_irqrestore(q->queue_lock, flags);
}
static void i2cblk_handle_request(struct i2cblk_device *device,struct request *req)
{
if ( i2cblk_process_io_request(device,req) )
req->errors++;
i2cblk_end_request(req);
return;
}
static int i2cblk_thread(void *data)
{
struct i2cblk_device *device = data;
struct request *req;
while ( ! kthread_should_stop() )
{
wait_event_interruptible(device->active_wq,kthread_should_stop() || (!list_empty(&device->active_queue)));
if ( list_empty(&device->active_queue) )
continue;
spin_lock_irq(&device->active_lock);
req = list_entry(device->active_queue.next,struct request,queuelist);
list_del_init(&req->queuelist);
spin_unlock_irq(&device->active_lock);
i2cblk_handle_request(device,req);
};
return(0);
}
^ permalink raw reply [flat|nested] 3+ messages in thread
* simple block device - request processing in threads
2017-03-03 10:12 simple block device - request processing in threads Andras Pal
@ 2017-03-04 13:52 ` Pranay Srivastava
2017-03-04 20:54 ` Andras Pal
0 siblings, 1 reply; 3+ messages in thread
From: Pranay Srivastava @ 2017-03-04 13:52 UTC (permalink / raw)
To: kernelnewbies
On Friday, March 3, 2017, Andras Pal <apal@szofi.net> wrote:
> Dear All,
>
> with some experience in low-level C programming, I started to develop a
> kernel module which allows I2C slave EEPROM-alike devices (EEPROMs, FRAMs,
> BBRAMs, etc) to be accessed as block devices. Since the i/o transactions
are
> relatively slow (say, 40k/sec), i'm using kernel threads. However, it
seems
> that while the read (rq_data_dir(req)) == 0) operations are fine, write
> operations (rq_data_dir != 0) seems to be lost. For instance, if I do `dd
> bs=512 count=32 of=/dev/i2cblk0`, only the first 8 sectors are fetched by
> blk_fetch_request(). I copy the critical/relevant/interesting parts after
this
> message. The code is based on drivers/block/nbd.c.
>
> In addition - according to printk()-based debugging - after each write
request,
> the kernel starts to access sectors in the order of 0, 24, 8, 56, 120,
64, 32
> (with 8 sectors == 1 page per request). Maybe it seeks for some
filesystems...?
> Can this feature be turned off (like setting
> disk->queue->backing_dev_info.ra_pages to zero in order to turn off
> readaheaad)?
>
> thanks in advance, cheers, Andras
>
>
/*****************************************************************************/
>
> static int i2cblk_process_io_request(struct i2cblk_device *device,struct
request *req)
> {
> int ret;
>
> /* i2cblk_transfer(): this function calls i2c_master_send/recv(), etc.
*/
>
> ret=i2cblk_transfer(device, blk_rq_pos(req), blk_rq_cur_sectors(req),
Shouldn't you be going over all bio(s)
in this req?
> bio_data(req->bio),
> rq_data_dir(req));
>
> return(ret);
> }
>
> static void i2cblk_request(struct request_queue *q)
> {
> struct request *req;
>
> while ( (req=blk_fetch_request(q)) != NULL )
> { struct i2cblk_device *device;
>
> if ( req->cmd_type != REQ_TYPE_FS )
> { __blk_end_request_all(req, -EIO);
> continue;
> }
>
> /* spin_unlock_irq(q->queue_lock); */
>
> device=req->rq_disk->private_data;
>
> spin_lock_irq(&device->active_lock);
> list_add_tail(&req->queuelist,&device->active_queue);
> spin_unlock_irq(&device->active_lock);
>
> wake_up(&device->active_wq);
>
> /* spin_lock_irq(q->queue_lock); */
> };
>
> }
>
> static void i2cblk_end_request(struct request *req)
> {
> int error;
> struct request_queue *q = req->q;
> unsigned long flags;
>
> error=(req->errors ? -EIO : 0);
>
> spin_lock_irqsave(q->queue_lock, flags);
> __blk_end_request_all(req, error);
> spin_unlock_irqrestore(q->queue_lock, flags);
> }
>
> static void i2cblk_handle_request(struct i2cblk_device *device,struct
request *req)
> {
> if ( i2cblk_process_io_request(device,req) )
> req->errors++;
>
> i2cblk_end_request(req);
>
> return;
> }
>
> static int i2cblk_thread(void *data)
> {
> struct i2cblk_device *device = data;
> struct request *req;
>
> while ( ! kthread_should_stop() )
> {
> wait_event_interruptible(device->active_wq,kthread_should_stop()
|| (!list_empty(&device->active_queue)));
>
> if ( list_empty(&device->active_queue) )
> continue;
>
> spin_lock_irq(&device->active_lock);
> req = list_entry(device->active_queue.next,struct
request,queuelist);
> list_del_init(&req->queuelist);
> spin_unlock_irq(&device->active_lock);
>
> i2cblk_handle_request(device,req);
> };
>
> return(0);
> }
>
>
> _______________________________________________
> Kernelnewbies mailing list
> Kernelnewbies at kernelnewbies.org
> https://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies
>
--
---P.K.S
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.kernelnewbies.org/pipermail/kernelnewbies/attachments/20170304/18f18d40/attachment.html
^ permalink raw reply [flat|nested] 3+ messages in thread
* simple block device - request processing in threads
2017-03-04 13:52 ` Pranay Srivastava
@ 2017-03-04 20:54 ` Andras Pal
0 siblings, 0 replies; 3+ messages in thread
From: Andras Pal @ 2017-03-04 20:54 UTC (permalink / raw)
To: kernelnewbies
Thanks, that was it! Therefore, it means that, i suppose, blk_rq_cur_sectors()
is meaningless and bio's are needed to be used exclusively.
Andras
On Sat, 4 Mar 2017, Pranay Srivastava wrote:
> On Friday, March 3, 2017, Andras Pal <apal@szofi.net> wrote:
>> Dear All,
>>
>> with some experience in low-level C programming, I started to develop a
>> kernel module which allows I2C slave EEPROM-alike devices (EEPROMs, FRAMs,
>> BBRAMs, etc) to be accessed as block devices. Since the i/o transactions
> are
>> relatively slow (say, 40k/sec), i'm using kernel threads. However, it
> seems
>> that while the read (rq_data_dir(req)) == 0) operations are fine, write
>> operations (rq_data_dir != 0) seems to be lost. For instance, if I do `dd
>> bs=512 count=32 of=/dev/i2cblk0`, only the first 8 sectors are fetched by
>> blk_fetch_request(). I copy the critical/relevant/interesting parts after
> this
>> message. The code is based on drivers/block/nbd.c.
>>
>> In addition - according to printk()-based debugging - after each write
> request,
>> the kernel starts to access sectors in the order of 0, 24, 8, 56, 120,
> 64, 32
>> (with 8 sectors == 1 page per request). Maybe it seeks for some
> filesystems...?
>> Can this feature be turned off (like setting
>> disk->queue->backing_dev_info.ra_pages to zero in order to turn off
>> readaheaad)?
>>
>> thanks in advance, cheers, Andras
>>
>>
> /*****************************************************************************/
>>
>> static int i2cblk_process_io_request(struct i2cblk_device *device,struct
> request *req)
>> {
>> int ret;
>>
>> /* i2cblk_transfer(): this function calls i2c_master_send/recv(), etc.
> */
>>
>> ret=i2cblk_transfer(device, blk_rq_pos(req), blk_rq_cur_sectors(req),
>
> Shouldn't you be going over all bio(s)
> in this req?
>
>> bio_data(req->bio),
>> rq_data_dir(req));
>>
>> return(ret);
>> }
>>
>> static void i2cblk_request(struct request_queue *q)
>> {
>> struct request *req;
>>
>> while ( (req=blk_fetch_request(q)) != NULL )
>> { struct i2cblk_device *device;
>>
>> if ( req->cmd_type != REQ_TYPE_FS )
>> { __blk_end_request_all(req, -EIO);
>> continue;
>> }
>>
>> /* spin_unlock_irq(q->queue_lock); */
>>
>> device=req->rq_disk->private_data;
>>
>> spin_lock_irq(&device->active_lock);
>> list_add_tail(&req->queuelist,&device->active_queue);
>> spin_unlock_irq(&device->active_lock);
>>
>> wake_up(&device->active_wq);
>>
>> /* spin_lock_irq(q->queue_lock); */
>> };
>>
>> }
>>
>> static void i2cblk_end_request(struct request *req)
>> {
>> int error;
>> struct request_queue *q = req->q;
>> unsigned long flags;
>>
>> error=(req->errors ? -EIO : 0);
>>
>> spin_lock_irqsave(q->queue_lock, flags);
>> __blk_end_request_all(req, error);
>> spin_unlock_irqrestore(q->queue_lock, flags);
>> }
>>
>> static void i2cblk_handle_request(struct i2cblk_device *device,struct
> request *req)
>> {
>> if ( i2cblk_process_io_request(device,req) )
>> req->errors++;
>>
>> i2cblk_end_request(req);
>>
>> return;
>> }
>>
>> static int i2cblk_thread(void *data)
>> {
>> struct i2cblk_device *device = data;
>> struct request *req;
>>
>> while ( ! kthread_should_stop() )
>> {
>> wait_event_interruptible(device->active_wq,kthread_should_stop()
> || (!list_empty(&device->active_queue)));
>>
>> if ( list_empty(&device->active_queue) )
>> continue;
>>
>> spin_lock_irq(&device->active_lock);
>> req = list_entry(device->active_queue.next,struct
> request,queuelist);
>> list_del_init(&req->queuelist);
>> spin_unlock_irq(&device->active_lock);
>>
>> i2cblk_handle_request(device,req);
>> };
>>
>> return(0);
>> }
>>
>>
>> _______________________________________________
>> Kernelnewbies mailing list
>> Kernelnewbies at kernelnewbies.org
>> https://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies
>>
>
> --
> ---P.K.S
>
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2017-03-04 20:54 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-03-03 10:12 simple block device - request processing in threads Andras Pal
2017-03-04 13:52 ` Pranay Srivastava
2017-03-04 20:54 ` Andras Pal
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.