Chinaunix首页 | 论坛 | 博客
  • 博客访问: 96837
  • 博文数量: 29
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 10
  • 用 户 组: 普通用户
  • 注册时间: 2014-09-01 19:43
文章分类
文章存档

2017年(4)

2015年(24)

2014年(1)

我的朋友

分类: LINUX

2015-07-11 13:39:58

原文地址:ll_rw_block解析Ⅱ 作者:zixin

void generic_make_request (int rw, struct buffer_head * bh)

{

    int major = MAJOR(bh->b_rdev);

    request_queue_t *q;

 

/* 检查,当进行IO请求时,缓冲块必须安装b_end_io函数*/

    if (!bh->b_end_io)

        BUG();

   

/*

*数组blk_size[MAJOR][MINOR]drivers/block/ll_rw_block.c中定义

*内容为各项具体设备中含有1024字节记录块的个数

*/

/* 取缓冲块所在块设备的最大扇区号*/

    if (blk_size[major]) {

        unsigned long maxsector = (blk_size[major][MINOR(bh->b_rdev)] << 1) + 1;

 

/* 请求传送的起始扇区号 */

unsigned long sector = bh->b_rsector;

 

/*每块的扇区数(记录块大小除以512)*/

        unsigned int count = bh->b_size >> 9;

 

/* 当读写请求越界时,通过printk在系统运行日志中登记出错信息返回*/

        if (maxsector < count || maxsector - count < sector) {

/* 保留BH_LockBH_Mapped状态*/

bh->b_state &= (1 << BH_Lock) | (1 << BH_Mapped);

            if (blk_size[major][MINOR(bh->b_rdev)]) {

               

                /* This may well happen - the kernel calls bread()

                   without checking the size of the device, e.g.,

                   when mounting a device. */

                printk(KERN_INFO

                       "attempt to access beyond end of device\n");

                printk(KERN_INFO "%s: rw=%d, want=%ld, limit=%d\n",

                       kdevname(bh->b_rdev), rw,

                       (sector + count)>>1,

                       blk_size[major][MINOR(bh->b_rdev)]);

            }

            /*读写失败*/

            bh->b_end_io(bh, 0);

            return;

        }

    }

 

    /*

     * 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.

     */

    do {

/*调用blk_get_queue->__blk_get_queue取块设备的IO请求结构*/         

        q = blk_get_queue(bh->b_rdev);

        if (!q) {

            printk(KERN_ERR

                   "generic_make_request: Trying to access nonexistent block-device %s(%ld)\n",

                   kdevname(bh->b_rdev), bh->b_rsector);

           /*当出错时,块的状态为"""无效"*/

            buffer_IO_error(bh);

            break;

        }

      /*调用块设备驱动程序的读写请求函数.

*即请求队列描述符qmake_request_fn 方法:

*创建一个读写数据结构并把它挂入该队列

*该方法由函数__make_request函数实现

*/

    } while (q->make_request_fn(q, rw, bh)); }

/*

*如果只是一种设备到另一种设备的映射,返回一个正整数,do-while循环再执行一遍

*如果完成的是对终极设备的操作,则返回0,结束循环

*/

 

 

request_queue_t *blk_get_queue(kdev_t dev)

{

    request_queue_t *ret;

    unsigned long flags;

 

    spin_lock_irqsave(&io_request_lock,flags);

    ret = __blk_get_queue(dev);

    spin_unlock_irqrestore(&io_request_lock,flags);

 

    return ret;

}

 

 

inline request_queue_t *__blk_get_queue(kdev_t dev)

{

/*

* blk_dev_struct blk_dev[]存储块设备的描述符

* 由块设备的主设备号索引 ,可以在blk_dev中找到相应blk_dev_struct结构

*/

    struct blk_dev_struct *bdev = blk_dev + MAJOR(dev);

 

/*

*先检查queue字段是否为空

*如果定义了.queue方法(驱程维护几个队列)

*调用queue字段指向的一个自定义驱程方法

*/

    if (bdev->queue)

        return bdev->queue(dev);

 

/*否则读.request_queue字段(驱程单个队列)*/

    else

        return &blk_dev[MAJOR(dev)].request_queue;

}

阅读(1428) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~