Re: problem in understanding direct IO and bio submission

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

 



Hi All,

<This is a followup of the similarly named post (yesterday) - 
that is why removing that text, and top-posting>.

Question:
Is there a restriction on the bi_size field of a bio submission for 
submitting an I/O for being aligned in case of direct write?

Observation:
Moving ahead with the problem previously posted (not copying the text here 
else it would make this post huge - please visit
http://permalink.gmane.org/gmane.linux.kernel.kernelnewbies/23158)
I observed that when I create a bio using bio_map_user (and passing aligned 
user space address to it) and have bi_size=(PAGE_SIZE aligned units), IO 
is being successfully performed and error being reported in case any failure 
at SCSI level takes place.

Whereas, as soon as I change the bi_size=(something unaligned) (and altering 
the first and last bio vector's offset accordingly) - IO is performed
successfully in case NO failure on SCSI side. But as soon as an error (like 
disconnection of device from switch) takes place, bio_end bio is being called
with bi_size as positive and /var/log/messages is being continuously flooded
with SCSI error messages like:

----
Oct 17 21:56:07 mgs02 kernel: end_request: I/O error, dev sdl, sector 33639
Oct 17 21:56:07 mgs02 kernel: sd 2:0:0:8: SCSI error: return code = 0x10000
Oct 17 21:56:07 mgs02 kernel: end_request: I/O error, dev sdl, sector 33639
Oct 17 21:56:07 mgs02 kernel: sd 2:0:0:8: SCSI error: return code = 0x10000
Oct 17 21:56:07 mgs02 kernel: end_request: I/O error, dev sdl, sector 33639
Oct 17 21:56:07 mgs02 kernel: sd 2:0:0:8: SCSI error: return code = 0x10000
Oct 17 21:56:07 mgs02 kernel: end_request: I/O error, dev sdl, sector 33639
Oct 17 21:56:07 mgs02 kernel: sd 2:0:0:8: SCSI error: return code = 0x10000
Oct 17 21:56:07 mgs02 kernel: end_request: I/O error, dev sdl, sector 33639
Oct 17 21:56:07 mgs02 kernel: sd 2:0:0:8: SCSI error: return code = 0x10000
Oct 17 21:56:07 mgs02 kernel: end_request: I/O error, dev sdl, sector 33639
Oct 17 21:56:07 mgs02 kernel: 2:0:0:8: SCSI error: return code = 0x10000
...
...
----
<kernel version: 2.6.16.27, SLES 10>

Where sector is actually the first requested sector for which bio was 
submitted. These errors do not cease until the device is plugged in - and 
after which the user space happily moves forward (completes the IO).

Also, I have placed a code like 

if(bio->bi_size > 0)
    return 1;

in the end_bio function call (first lines) - to discard sub-completion 
calls made to the routine.

the code for creating the bio is:

-----
<snip>
      size = end_addr - addr;
      map_e_addr = (char *)(((__u64)end_addr + PAGE_SIZE - 1) & \
                    (~(PAGE_SIZE - 1)));
      size = (map_e_addr - map_addr);
      while ((map_addr)<map_e_addr) {
         bio = bio_map_user(bdev_get_queue(bdev), bdev,(unsigned long) \
                map_addr,(unsigned long) (size), rw==READ);
         if(!bio){      
            dump(" bio_map_user failed\n");
            retval = -EFAULT;   
            return retval;      
         }              
                        
         bio->bi_sector = sector;
         bio->bi_bdev = bdev;
         bio->bi_rw = rw;
         bio->bi_private = greq;
         bio->bi_end_io = mf_end_bio; 
 
                        
         bio->bi_io_vec[0].bv_offset = bsize;
         bio->bi_io_vec[0].bv_len = (PAGE_SIZE - bsize);

         if( (__u64)end_addr % PAGE_SIZE){
            bsize = (unsigned long)((__u64)end_addr - ((__u64)end_addr & \
                     ~(PAGE_SIZE - 1))); 
            bio->bi_io_vec[bio->bi_vcnt-1].bv_len = bsize;
         }              
         bsize = 0;     
                                
         bio->bi_size = (unsigned long)(end_addr - start_addr);   
         bio->bi_next = top_bio;
         blk_queue_bounce(bdev_get_queue(bdev), &bio);
         top_bio=bio;   
         bio = NULL;    
         total_bios++;  
         map_addr += size;
         bsize_total += (end_addr - start_addr); 

         size = (unsigned long) (map_e_addr - map_addr); 
         if(map_addr>=map_e_addr)
            break;              
<snip>              
-----


Where:
- start_addr and end_addr are the starting and ending addresses of the buffer
  allocated by the user space process requesting IO
- map_addr and map_e_addr are starting and ending address of aligned user space
  address - map_addr aligned to PAGE_SIZE less than start_addr and map_e_addr
  aligned to PAGE_SIZE more than end_addr
- bsize is the offset of the first page of the bio vector - (start_addr - 
  map_addr).
- It is assuring that at max 3 pages are being requested (test setup) so that
  request does not overflow max allowable io vectors in bio

Any help/pointer/reference would be really appreciated.

Also, this is a test code and hence does not confirm to good coding styles -
please ignore that.

Regards
Shreyansh


Shreyansh Jain <shreyansh.jain <at> gmail.com> writes:
[removed the previous text to curtail the length of this post]


--
To unsubscribe from this list: send an email with
"unsubscribe kernelnewbies" to ecartis@xxxxxxxxxxxx
Please read the FAQ at http://kernelnewbies.org/FAQ


[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