Block device sends a bio process 2.6.36

Source: Internet
Author: User

Sync_request is not necessarily the case. You can call other functions.

Submit_bio

 

// Bio and bio_vec are local variables.

Static intSync_request

(Struct page * page, struct block_device * bdev, int rw)
{
Struct bio;
Struct bio_vec;
Struct completion complete;

Bio_init (& bio );
Bio. bi_io_vec = & bio_vec;
Bio_vec.bv_page = page; // transmits the entire page
Bio_vec.bv_len = PAGE_SIZE;
Bio_vec.bv_offset = 0;
Bio. bi_vcnt = 1; // A bio_vec
Bio. bi_idx = 0; // The current value is 0.
Bio. bi_size = PAGE_SIZE;
Bio. bi_bdev = bdev;
Bio. bi_sector = page-> index * (PAGE_SIZE> 9); // how is this calculated?
Init_completion (& complete );
Bio. bi_private = & complete;
Bio. bi_end_io = request_complete;

Submit_bio (rw, & bio); // submit
Generic_unplug_device (bdev_get_queue (bdev ));
Wait_for_completion (& complete); // wait for completion

Return test_bit (BIO_UPTODATE, & bio. bi_flags )? 0:-EIO;
}

 

 

VoidSubmit_bio

(Int rw, struct bio * bio)
{
Int count = bio_sectors (bio); // converts it to the number of sector, in the unit of 512B

...

...

Generic_make_request (bio );
}

 

/*
* We only want one-> make_request_fn to be active at a time,
* Else stack usage with stacked devices cocould be a problem.
* So use current-> bio_list to keep a list of requests
* Submited by a make_request_fn function.
* Current-> bio_list is also used as a flag to say if
* Generic_make_request is currently active in this task or not.
* If it is NULL, then no make_request is active. If it is non-NULL,
* Then a make_request is active, and new requests shocould be added
* At the tail
*/
VoidGeneric_make_request

(Struct bio * bio)
{
Struct bio_list bio_list_on_stack;

If (current-> bio_list ){
/* Make_request is active */
Bio_list_add (current-> bio_list, bio );
Return;
}
/* Following loop may be a bit non-obvious, and so deserves some
* Explanation.
* Before entering the loop, bio-> bi_next is null (as all callers
* Ensure that) So we have a list with a single bio.
* We pretend that we have just taken it off a longer list, so
* We assign bio_list to a pointer to the bio_list_on_stack,
* Thus initialising the bio_list of New BIOS to be
* Added. _ generic_make_request may indeed add some more BIOS
* Through a recursive call to generic_make_request. If it
* Did, we find a non-null value in bio_list and re-enter the loop
* From the top. In this case we really did just take the bio
* Of the top of the list (No pretending) And so remove it from
* Bio_list, and call into _ generic_make_request again.
*
* The loop was structured like this to make only one call
* _ Generic_make_request (which is important as it is large and
* Inlined) and to keep the structure simple.
*/
BUG_ON (bio-> bi_next );
Bio_list_init (& bio_list_on_stack );
Current-> bio_list = & bio_list_on_stack;
Do {
_ Generic_make_request (bio );
Bio = bio_list_pop (current-> bio_list );
} While (bio );
Current-> bio_list = NULL;/* deactivate */
}

 

Static inline void_ Generic_make_request (

Struct bio * bio)
{
Struct request_queue * q;
Sector_t old_sector;
Int ret, nr_sectors = bio_sectors (bio );
Dev_t old_dev;
Int err =-EIO;

Might_sleep ();

If (bio_check_eod (bio, nr_sectors ))
Goto end_io;

/*
* Resolve the mapping until finished. (drivers are
* Still free to implement/resolve their own stacking
* By explicitly returning 0)
*
* NOTE: we don't repeat the blk_size check for each new device.
* Stacking drivers are expected to know what they are doing.
*/
Old_sector =-1;
Old_dev = 0;
Do {
Char B [BDEVNAME_SIZE];

Q = bdev_get_queue (bio-> bi_bdev );
If (unlikely (! Q )){
Printk (KERN_ERR
"Generic_make_request: Trying to access"
"Nonexistent block-device % s (% Lu)/n ",
Bdevname (bio-> bi_bdev, B ),
(Long) bio-> bi_sector );
Goto end_io;
}

If (unlikely (! (Bio-> bi_rw & REQ_DISCARD )&&
Nr_sectors> queue_max_hw_sectors (q ))){
Printk (KERN_ERR "bio too big device % s (% u> % u)/n ",
Bdevname (bio-> bi_bdev, B ),
Bio_sectors (bio ),
Queue_max_hw_sectors (q ));
Goto end_io;
}

If (unlikely (test_bit (QUEUE_FLAG_DEAD, & q-> queue_flags )))
Goto end_io;

If (should_fail_request (bio ))
Goto end_io;

/*
* If this device has partitions, remap block n
* Of partition p to block n + start (p) of the disk.
*/
Blk_partition_remap (bio );

If (bio_integrity_enabled (bio) & bio_integrity_prep (bio ))
Goto end_io;

If (old_sector! =-1)
Trace_block_remap (q, bio, old_dev, old_sector );

Old_sector = bio-> bi_sector;
Old_dev = bio-> bi_bdev-> bd_dev;

If (bio_check_eod (bio, nr_sectors ))
Goto end_io;

If (bio-> bi_rw & REQ_DISCARD )&&
(! Blk_queue_discard (q) |
(Bio-> bi_rw & req_secure )&&
! Blk_queue_secdiscard (q )))){
Err =-eopnotsupp;
Goto end_io;
}

Trace_block_bio_queue (Q, bio );

Ret = Q->Make_request_fn

(Q, bio); // this should be the registered request function.
} While (RET );

Return;

End_io:
Bio_endio (Bio, err );
}

 

 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.