All of lore.kernel.org
 help / color / mirror / Atom feed
* 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.