block裝置 發送一個bio的過程 2.6.36

來源:互聯網
上載者:User

sync_request 這個是不一定的,可以call別的函數

    submit_bio

 

//這個的bio 和 bio_vec是local變數

static int sync_request

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

    bio_init(&bio);
    bio.bi_io_vec = &bio_vec;
    bio_vec.bv_page = page;  //傳送整個page
    bio_vec.bv_len = PAGE_SIZE;
    bio_vec.bv_offset = 0;
    bio.bi_vcnt = 1;          //就一個bio_vec
    bio.bi_idx = 0;           //當前為0
    bio.bi_size = PAGE_SIZE;
    bio.bi_bdev = bdev;
    bio.bi_sector = page->index * (PAGE_SIZE >> 9);// 這個咋算出來的?
    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); // 這裡等待完成

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

 

 

void submit_bio

(int rw, struct bio *bio)
{
    int count = bio_sectors(bio); // 轉換成了sector數,以512B為單位

    ...

    ...

    generic_make_request(bio);
}

 

/*
 * We only want one ->make_request_fn to be active at a time,
 * else stack usage with stacked devices could 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 should be added
 * at the tail
 */
void generic_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 to
     * __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 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); //  這個應該就是註冊進去的request函數
    } while (ret);

    return;

end_io:
    bio_endio(bio, err);
}

 

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

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.