simple block device - request processing in threads
From: Andras Pal <hidden>
Date: 2017-03-04 20:54:17
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 [off-list ref] wrote:quoted
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 transactionsarequoted
relatively slow (say, 40k/sec), i'm using kernel threads. However, itseemsquoted
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 afterthisquoted
message. The code is based on drivers/block/nbd.c. In addition - according to printk()-based debugging - after each writerequest,quoted
the kernel starts to access sectors in the order of 0, 24, 8, 56, 120,64, 32quoted
(with 8 sectors == 1 page per request). Maybe it seeks for somefilesystems...?quoted
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/*****************************************************************************/quoted
static int i2cblk_process_io_request(struct i2cblk_device *device,structrequest *req)quoted
{ int ret; /* i2cblk_transfer(): this function calls i2c_master_send/recv(), etc.*/quoted
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?quoted
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,structrequest *req)quoted
{ 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)));quoted
if ( list_empty(&device->active_queue) ) continue; spin_lock_irq(&device->active_lock); req = list_entry(device->active_queue.next,structrequest,queuelist);quoted
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