simple block device - request processing in threads
Andras Pal
apal at szofi.net
Sat Mar 4 15:54:17 EST 2017
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 at 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
>
More information about the Kernelnewbies
mailing list