Block device layer analysis 1

Source: Internet
Author: User

I. Summary

Figure 1 is a hierarchical implementation of block device operations. When a process calls read to read a file, the kernel executes the following process: first, it reads the file block that has been cached through the VFS layer, this cache is read by a buffer_head structure. If the file block to be read is not cached, it will be read from the file system. This is the ing layer of the file system. It is referenced through an address_space structure, call the file system READ function (readpage) to read data of a page. This READ function is different for different file systems. When it reads data from a disk, it links the data page to the cache. When it reads data again, it does not need to read data from the disk again. Instead of operating the disk directly, the readpage () function initializes the request into a bio structure and submits it to the general block layer (generic
Block Layer ).

Figure 1

It is done through submit_bio. The general block layer then calls the IO scheduler of the corresponding device and uses the scheduler's scheduling algorithm to merge the bio into an existing request or create a new request, insert the newly created request to the Request queue of the device. This completes the I/O scheduling layer. The last step is the work done by the block device driver. The IO scheduler sends a request queue to the block driver. The block driver processes the requests in the queue until the queue is empty.

II. General block layer)

The general block layer operates on a bio structure. The main data domain of this structure is,

Unsigned short
Bi_vcnt;

Struct bio_vec * bi_io_vec;
/* The actual VEC list */

This is the data vector to be read and written, and each struct bio_vec
Is a segment.

// This function is mainly used to call generic_make_request () to complete the work:

Void submit_bio (int rw, struct bio * bio)

{

......

Generic_make_request (bio );

}

// The main function of this function is to pass bio to the driver for processing.

Void generic_make_request (struct bio * bio)

{

......

Do {

Char B [bdevname_size];

// Obtain the queue for each block device.

Q = bdev_get_queue (bio-> bi_bdev );

/*

* If this device has partitions, REMAP Block N

* Of partition P to block N + start (p) of the disk.

*/

Blk_partition_remap (bio); // block device partition information conversion, such as converting the offset address of a partition to the absolute offset relative to the entire block device.

Old_sector = bio-> bi_sector;

Old_dev = bio-> bi_bdev-> bd_dev;

......

// This is the request processing function of the block device queue. It is initialized when a block device creates a request queue.

// For devices such as IDE, It is _ make_request (). But it is different for ramdisk.

Ret = Q-> make_request_fn (Q, bio );
// _ Make_request () and so on

} While (RET );

}

// The main function of this function is to call the IO scheduling algorithm to merge bio or insert it to a suitable position in the queue.

Static int _ make_request (request_queue_t * q, struct bio * bio)

{

Struct Request * req;

Int el_ret, nr_sectors, barrier, err;

Const unsigned short PRIO = bio_prio (bio );

Const int sync = bio_sync (bio );

Int rw_flags;

Nr_sectors = bio_sectors (bio );

// Process high-end memory

Blk_queue_bounce (Q, & Bio );

Spin_lock_irq (Q-> queue_lock );

// Test whether the node can be merged. I/O scheduling algorithm is ignored in this article.

El_ret = elv_merge (Q, & req, bio );

Switch (el_ret ){

// The first two types can be merged.

Case elevator_back_merge:

......

Goto out;

Case elevator_front_merge:

......

Goto out;

// Cannot be merged. A new request is required.

/* Elv_no_merge: Elevator says don't/can't merge .*/

Default:

;

}

Get_rq:

Rw_flags = bio_data_dir (bio );

If (Sync)

Rw_flags | = req_rw_sync;

// Create a new request

Req = get_request_wait (Q, rw_flags, bio );

// Initialize the request.

Init_request_from_bio (req, bio );

Spin_lock_irq (Q-> queue_lock );

If (elv_queue_empty (q) // process an empty queue

Blk_plug_device (Q );

Add_request (Q, req );
// Add new requests to the queue

Out:

If (Sync) // If synchronization is required, process the request immediately

_ Generic_unplug_device (Q );

Spin_unlock_irq (Q-> queue_lock );

Return 0;

End_io:

Bio_endio (Bio, nr_sectors <9, err );

Return 0;

}

// Trigger the block Device Driver for real Io operations

Void _ generic_unplug_device (request_queue_t * q)

{

If (unlikely (blk_queue_stopped (q )))

Return;

If (! Blk_remove_plug (q ))

Return;

Q-> request_fn (Q );
// The request processing function of the device, which belongs to the driver layer.

}

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.