Jump to content

Redirect bio to another device

Gorizon's Photo
Posted Jun 19 2010 07:56 AM
4037 Views

Hello all! I have been trying to write a stacking block device driver and I used 3rd edition of "Linux Device Drivers" as a handbook for that.

They offer an example (sbull, IYR) where one of the ways to implement I/O handling was direct sbull_make_request() function, which works with bios without a queue. They also say, that every completion of bio should be done with bio_endio() routine and

that if the make_request function returns a nonzero value, the bio is submitted again.

Quote

A “stacking” driver can, therefore, modify the bi_bdev field to point to a differ- ent device, change the starting sector value, then return


The thing is, all of a sudden, today in 2010 I found that in my 2.30 kernel bio_endio function is without size argument! And also, if I return something other than 0 from my make_request(), the system crashes. If I don't do bio_endio, the system freezes(apparently waiting for completion)
Please anybody, help me redirect bio from one device to another, here is the cut of my code:




    static int versioned_make_request(request_queue_t *q, struct bio *bio)
    {
    	...
    	
    	start_chunk=(unsigned )(bio->bi_sector) * KERNEL_SECTOR_SIZE /(dev->chunk_size);
    	chunks=(bio->bi_size / dev->chunk_size);
    
    	
    	...

    	for (i = start_chunk; i < start_chunk + chunks;	i++) { //assume request is one chunk, therefore no need to split between slots
    		if (bio_data_dir(bio)==WRITE) //memory -> device
    		{
    			if (version_idx!=dev->current_version) return -EROFS;//we only can read from previous versions
    			...
    		        bio->bi_sector=(DATA_OFFSET+dev->vchunks[i].write_slot*dev->slot_size+i)*dev->chunk_size/KERNEL_SECTOR_SIZE;
    			...
    
    		}
    		if (bio_data_dir(bio)==READ) //device -> memory
    		{
    			...
    			bio->bi_sector=(DATA_OFFSET+designated_slot*dev->slot_size+i)*dev->chunk_size/KERNEL_SECTOR_SIZE;
    			...
    		}
    	}
    	bio->bi_bdev=dev->base_device;
    
    	bio_endio(bio, 0);
    	printk("\n");
    	return -1;
    }


Tags:
0 Subscribe


1 Reply

0
  Gorizon's Photo
Posted Jun 19 2010 08:25 PM

Oh, the answer is so simple- DON"T end bio when you return nonzero, because then system will try to reservice already dead bio