/* * 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 */ };//块设备数组,一共7个,每个设备一个
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. */ static void add_request(struct blk_dev_struct * dev, struct request * req)//向请求项链表中加入一请求项,dev指定块设备结构指针,req请求项
{ struct request * tmp;
req->next = NULL;//下一项置空
cli();//关中断
if (req->bh) req->bh->b_dirt = 0;//修改标志0为未修改,1为修改
if (!(tmp = dev->current_request)) {//当前设备所指向的当前请求项为空时,也就是当前设备暂时还没有请求项
dev->current_request = req;//当前请求项指向于req
sti();//开中断
(dev->request_fn)();//执行请请求函数,如do_hd_request
return; } for ( ; tmp->next ; tmp=tmp->next)//当前设备所指向的当前请求项不为空时,则插入请求项数组中为
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)//将请求项插入到请求链表中,major主设备号,rw指定命令,bh存放数据的缓冲区的头指针
{ struct request * req;//新建请求项
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)) {//体现高速缓冲区的用意,在数据 可靠的情况下(要读取硬盘上的的数据与缓冲区上的数据相同,要写入的数据与缓冲区上的相同 )这一次操作可以返顺回,没有必要增加新 求项,bh->b_dirt修改标志0为未修改,1为修改,, bh->b_uptodate更新标志,缓冲区上的数据是否为块上的数据同步,1为缓冲区上的数据与硬盘上的数据同步一样
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);//但写项只可占用请求链表中的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);//否则,由于请求链表满,没有空闲的,所以让本次请求操作先睡眠,将当前任务置为不可中断的等待状态,放入wait_for_request队列中来,进行进程调度,当又轮到本程序执行时执行下面的语句goto repeat;
goto repeat; } /* fill up the request-info, and add it to the queue *///t向空闲链表填写相关停息
req->dev = bh->b_dev;//设备号
req->cmd = rw;//命令
req->errors=0;//操作的数据次数
req->sector = bh->b_blocknr<<1;//块号转为扇区(1块=2扇区),起始扇区
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_block(int rw, struct buffer_head * bh)//底层读写数据块函数,由fs/buffer.c函数调用 ,主要创建读写设备的请示谋项,并插入到请求链表中去
{ unsigned int major;
if ((major=MAJOR(bh->b_dev)) >= NR_BLK_DEV || !(blk_dev[major].request_fn)) {//如主设备号为非法的,或块设备数组中请求项函数指针为空时,
printk("Trying to read nonexistent block-device\n\r"); return; } make_request(major,rw,bh);//将请求项插入到请求链表中
}
void blk_dev_init(void)//块设备初始化函数main.c line 128 行调用,
{ int i;
for (i=0 ; i<NR_REQUEST ; i++) {//初始化请求数组
request[i].dev = -1; request[i].next = NULL; } }
|