Re: simple block device - request processing in threads

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 





On Friday, March 3, 2017, Andras Pal <apal@xxxxxxxxx> 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@xxxxxxxxxxxxxxxxx
> https://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies
>

--
        ---P.K.S

_______________________________________________
Kernelnewbies mailing list
Kernelnewbies@xxxxxxxxxxxxxxxxx
https://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies

[Index of Archives]     [Newbies FAQ]     [Linux Kernel Mentors]     [Linux Kernel Development]     [IETF Annouce]     [Git]     [Networking]     [Security]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux SCSI]     [Linux ACPI]
  Powered by Linux