分类: 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_Lock和BH_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.
*/
/*调用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;
}
/*调用块设备驱动程序的读写请求函数.
*即请求队列描述符q的make_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;
}