<br><br>On Friday, March 3, 2017, Andras Pal &lt;<a href="mailto:apal@szofi.net">apal@szofi.net</a>&gt; wrote:<br>&gt; Dear All,<br>&gt;<br>&gt; with some experience in low-level C programming, I started to develop a<br>&gt; kernel module which allows I2C slave EEPROM-alike devices (EEPROMs, FRAMs,<br>&gt; BBRAMs, etc) to be accessed as block devices. Since the i/o transactions are<br>&gt; relatively slow (say, 40k/sec), i&#39;m using kernel threads. However, it seems<br>&gt; that while the read (rq_data_dir(req)) == 0) operations are fine, write<br>&gt; operations (rq_data_dir != 0) seems to be lost. For instance, if I do `dd<br>&gt; bs=512 count=32 of=/dev/i2cblk0`, only the first 8 sectors are fetched by<br>&gt; blk_fetch_request(). I copy the critical/relevant/interesting parts after this<br>&gt; message. The code is based on drivers/block/nbd.c.<br>&gt;<br>&gt; In addition - according to printk()-based debugging - after each write request,<br>&gt; the kernel starts to access sectors in the order of 0, 24, 8, 56, 120, 64, 32<br>&gt; (with 8 sectors == 1 page per request). Maybe it seeks for some filesystems...?<br>&gt; Can this feature be turned off (like setting<br>&gt; disk-&gt;queue-&gt;backing_dev_info.ra_pages to zero in order to turn off<br>&gt; readaheaad)?<br>&gt;<br>&gt; thanks in advance, cheers, Andras<br>&gt;<br>&gt; /*****************************************************************************/<br>&gt;<br>&gt; static int i2cblk_process_io_request(struct i2cblk_device *device,struct request *req)<br>&gt; {<br>&gt;   int    ret;<br>&gt;<br>&gt;   /* i2cblk_transfer(): this function calls i2c_master_send/recv(), etc. */<br>&gt;<br>&gt;   ret=i2cblk_transfer(device, blk_rq_pos(req), blk_rq_cur_sectors(req),<br><br>Shouldn&#39;t you be going over all bio(s)<br>in this req? <br><br>&gt;                  bio_data(req-&gt;bio),<br>&gt;                  rq_data_dir(req));<br>&gt;<br>&gt;   return(ret);<br>&gt; }<br>&gt;<br>&gt; static void i2cblk_request(struct request_queue *q)<br>&gt; {<br>&gt;   struct request *req;<br>&gt;<br>&gt;   while ( (req=blk_fetch_request(q)) != NULL )<br>&gt;    {     struct  i2cblk_device   *device;<br>&gt;<br>&gt;          if ( req-&gt;cmd_type != REQ_TYPE_FS )<br>&gt;           {      __blk_end_request_all(req, -EIO);<br>&gt;                  continue;<br>&gt;           }<br>&gt;<br>&gt;          /* spin_unlock_irq(q-&gt;queue_lock); */<br>&gt;<br>&gt;          device=req-&gt;rq_disk-&gt;private_data;<br>&gt;<br>&gt;          spin_lock_irq(&amp;device-&gt;active_lock);<br>&gt;          list_add_tail(&amp;req-&gt;queuelist,&amp;device-&gt;active_queue);<br>&gt;          spin_unlock_irq(&amp;device-&gt;active_lock);<br>&gt;<br>&gt;          wake_up(&amp;device-&gt;active_wq);<br>&gt;<br>&gt;          /* spin_lock_irq(q-&gt;queue_lock); */<br>&gt;    };<br>&gt;<br>&gt; }<br>&gt;<br>&gt; static void i2cblk_end_request(struct request *req)<br>&gt; {<br>&gt;   int                    error;<br>&gt;   struct request_queue   *q = req-&gt;q;<br>&gt;   unsigned long          flags;<br>&gt;<br>&gt;   error=(req-&gt;errors ? -EIO : 0);<br>&gt;<br>&gt;   spin_lock_irqsave(q-&gt;queue_lock, flags);<br>&gt;   __blk_end_request_all(req, error);<br>&gt;   spin_unlock_irqrestore(q-&gt;queue_lock, flags);<br>&gt; }<br>&gt;<br>&gt; static void i2cblk_handle_request(struct i2cblk_device *device,struct request *req)<br>&gt; {<br>&gt;   if ( i2cblk_process_io_request(device,req) )<br>&gt;          req-&gt;errors++;<br>&gt;<br>&gt;   i2cblk_end_request(req);<br>&gt;<br>&gt;   return;<br>&gt; }<br>&gt;<br>&gt; static int i2cblk_thread(void *data)<br>&gt; {<br>&gt;   struct i2cblk_device   *device = data;<br>&gt;   struct request         *req;<br>&gt;<br>&gt;   while ( ! kthread_should_stop() )<br>&gt;    {<br>&gt;          wait_event_interruptible(device-&gt;active_wq,kthread_should_stop() || (!list_empty(&amp;device-&gt;active_queue)));<br>&gt;<br>&gt;          if ( list_empty(&amp;device-&gt;active_queue) )<br>&gt;                  continue;<br>&gt;<br>&gt;          spin_lock_irq(&amp;device-&gt;active_lock);<br>&gt;          req = list_entry(device-&gt;active_queue.next,struct request,queuelist);<br>&gt;          list_del_init(&amp;req-&gt;queuelist);<br>&gt;          spin_unlock_irq(&amp;device-&gt;active_lock);<br>&gt;<br>&gt;          i2cblk_handle_request(device,req);<br>&gt;    };<br>&gt;<br>&gt;   return(0);<br>&gt; }<br>&gt;<br>&gt;<br>&gt; _______________________________________________<br>&gt; Kernelnewbies mailing list<br>&gt; <a href="mailto:Kernelnewbies@kernelnewbies.org">Kernelnewbies@kernelnewbies.org</a><br>&gt; <a href="https://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies">https://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies</a><br>&gt;<br><br>-- <br>        ---P.K.S<br><br>