📄 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];/* * 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 */};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) /* 将请求项加入相应块设备的请求队列,若队列为空则直接调用块设备的处理函数 */{ struct request * tmp; req->next = NULL;/* 初始化请求项:next置为空;清缓冲区的脏标志 */ 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 ((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; 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)) {/* 这里体现了缓冲区的用意(b_dirt标志表示缓冲块中的数据是否已被修改过。b_update标志用于表示缓冲块中的数据是与块设备上同步的) */ 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)/* 请求项数组的后1/3为读请求项 */ 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_block(int rw, struct buffer_head * bh){ 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)/*块设备初始化*/{ int i; for (i=0 ; i<NR_REQUEST ; i++) {/*初始化块设备请求数组,将所有请求设置为空闲*/ request[i].dev = -1; request[i].next = NULL; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -