linux-ll_rw_blk.c

/*
*  linux/kernel/blk_dev/ll_rw.c
*                        //--用于执行低层块设备读/写操作,是所有块设备与系统其他部分的接口程序
*
* (C) 1991 Linus Torvalds
*/
/*
* This handles all read/write requests to block devices
*/
#include <errno.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <asm/system.h>
#include "blk.h"
/*
* The request-struct contains all necessary data
* to load a nr of sectors into memory
*/
struct request request[NR_REQUEST];                //--NR_REQUEST=32
/*
* used to wait on when there are no free requests
*/
struct task_struct * wait_for_request = NULL;
/* blk_dev_struct is:
*    do_request-address
*    next-request
*/
struct blk_dev_struct blk_dev[NR_BLK_DEV] = {        
    { NULL, NULL },        /* no_dev */
    { NULL, NULL },        /* dev mem */
    { NULL, NULL },        /* dev fd */
    { NULL, NULL },        /* dev hd */
    { NULL, NULL },        /* dev ttyx */
    { NULL, NULL },        /* dev tty */
    { NULL, NULL }        /* dev lp */
};
/*
* blk_size contains the size of all block-devices:
*
* blk_size[MAJOR][MINOR]
*
* if (!blk_size[MAJOR]) then no minor size checking is done.
*/
int * blk_size[NR_BLK_DEV] = { NULL, NULL, };
static inline void lock_buffer(struct buffer_head * bh)
{                                    //--锁定指定缓冲块
    cli();
    while (bh->b_lock)                //--如果已经被锁定,则是自己睡眠,直到...
        sleep_on(&bh->b_wait);
    bh->b_lock=1;
    sti();
}
static inline void unlock_buffer(struct buffer_head * bh)
{                                    //--解锁锁定的缓冲区
    if (!bh->b_lock)
        printk("ll_rw_block.c: buffer not locked/n/r");
    bh->b_lock = 0;
    wake_up(&bh->b_wait);
}
/*
* add-request adds a request to the linked list.
* It disables interrupts so that it can muck with the
* request-lists in peace.
*
* Note that swapping requests always go before other requests,
* and are done in the order they appear.
*/
static void add_request(struct blk_dev_struct * dev, struct request * req)
{                                    //--向链表中加入请求项
    struct request * tmp;
    req->next = NULL;
    cli();
    if (req->bh)
        req->bh->b_dirt = 0;
    if (!(tmp = dev->current_request)) {        //--检查设备是否正忙
        dev->current_request = req;                //--若目前该设备没有请求项,本次是唯一一个请求
        sti();                                    //--则将块设备当前请求指针直接指向该请求项
        (dev->request_fn)();
        return;
    }
    for ( ; tmp->next ; tmp=tmp->next) {        //--设备已经有当前请求项在处理
        if (!req->bh)
            if (tmp->next->bh)
                break;
            else
                continue;
        if ((IN_ORDER(tmp,req) ||
            !IN_ORDER(tmp,tmp->next)) &&
            IN_ORDER(req,tmp->next))            //--电梯算法
            break;
    }
    req->next=tmp->next;
    tmp->next=req;
    sti();
}
static void make_request(int major,int rw, struct buffer_head * bh)
{                                                //--创建请求项,并插入请求队列中
    struct request * req;    //--major主设备号/rw指定命令/bh数据的缓冲区头指针
    int rw_ahead;
/* WRITEA/READA is special case - it is not really needed, so if the */
/* buffer is locked, we just forget about it, else it's a normal read */
    if (rw_ahead = (rw == READA || rw == WRITEA)) {
        if (bh->b_lock)
            return;
        if (rw == READA)
            rw = READ;
        else
            rw = WRITE;
    }
    if (rw!=READ && rw!=WRITE)
        panic("Bad block dev command, must be R/W/RA/WA");
    lock_buffer(bh);
    if ((rw == WRITE && !bh->b_dirt) || (rw == READ && bh->b_uptodate)) {
        unlock_buffer(bh);
        return;
    }
repeat:
/* we don't allow the write-requests to fill up the queue completely:
* we want some room for reads: they take precedence. The last third
* of the requests are only for reads.
*/
    if (rw == READ)
        req = request+NR_REQUEST;
    else
        req = request+((NR_REQUEST*2)/3);
/* find an empty request */
    while (--req >= request)                //--搜索空闲的地方存放请求
        if (req->dev<0)
            break;
/* if none found, sleep on new requests: check for rw_ahead */
    if (req < request) {                    //--如果没有空闲的地方,则本次操作睡眠等待
        if (rw_ahead) {
            unlock_buffer(bh);
            return;
        }
        sleep_on(&wait_for_request);
        goto repeat;
    }
/* fill up the request-info, and add it to the queue */
    req->dev = bh->b_dev;                    //--填写信息,并加入队列
    req->cmd = rw;
    req->errors=0;
    req->sector = bh->b_blocknr<<1;
    req->nr_sectors = 2;
    req->buffer = bh->b_data;
    req->waiting = NULL;
    req->bh = bh;
    req->next = NULL;
    add_request(major+blk_dev,req);
}
void ll_rw_page(int rw, int dev, int page, char * buffer)
{                                            //--低级页面读写操作,与make_request类似
    struct request * req;                    //--以页面(4K)为单位访问块设备数据,即每次读/写8个扇区
    unsigned int major = MAJOR(dev);
    if (major >= NR_BLK_DEV || !(blk_dev[major].request_fn)) {
        printk("Trying to read nonexistent block-device/n/r");
        return;
    }
    if (rw!=READ && rw!=WRITE)
        panic("Bad block dev command, must be R/W");
repeat:
    req = request+NR_REQUEST;
    while (--req >= request)
        if (req->dev<0)
            break;
    if (req < request) {
        sleep_on(&wait_for_request);
        goto repeat;
    }
/* fill up the request-info, and add it to the queue */
    req->dev = dev;
    req->cmd = rw;
    req->errors = 0;
    req->sector = page<<3;
    req->nr_sectors = 8;
    req->buffer = buffer;
    req->waiting = current;
    req->bh = NULL;
    req->next = NULL;
    current->state = TASK_UNINTERRUPTIBLE;
    add_request(major+blk_dev,req);
    schedule();
}    
void ll_rw_block(int rw, struct buffer_head * bh)    //--低级数据块读写操作
{                                //--块设备驱动程序与系统其它部分的接口函数
    unsigned int major;
    if ((major=MAJOR(bh->b_dev)) >= NR_BLK_DEV ||
    !(blk_dev[major].request_fn)) {                    //--操作函数:do_hd_request,do_fd_request,do_rd_requset.
        printk("Trying to read nonexistent block-device/n/r");
        return;
    }
    make_request(major,rw,bh);
}
void blk_dev_init(void)            //--块设备初始化程序,main.c中调用
{
    int i;
    for (i=0 ; i<NR_REQUEST ; i++) {
        request[i].dev = -1;
        request[i].next = NULL;
    }
}
|xGv00|fcc8d4de8197f69fde70263fb4d52380
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值