⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ll_rw_blk.c.txt

📁 Linux块设备驱动分析与模拟实现
💻 TXT
📖 第 1 页 / 共 2 页
字号:
  1 /*
  2  *  linux/kernel/blk_dev/ll_rw.c
  3  *
  4  * Copyright (C) 1991, 1992 Linus Torvalds
  5  */
  6 
  7 /*
  8  * This handles all read/write requests to block devices
  9  */
 10 #include <linux/sched.h>
 11 #include <linux/kernel.h>
 12 #include <linux/kernel_stat.h>
 13 #include <linux/errno.h>
 14 #include <linux/string.h>
 15 #include <linux/config.h>
 16 #include <linux/locks.h>
 17 
 18 #include <asm/system.h>
 19 
 20 #include "blk.h"
 21 
 22 #ifdef CONFIG_SBPCD
 23 extern u_long sbpcd_init(u_long, u_long);
 24 #endif CONFIG_SBPCD
 25 
 26 /*
 27  * The request-struct contains all necessary data
 28  * to load a nr of sectors into memory
 29  */
 30 static struct request all_requests[NR_REQUEST];
 31 
 32 /*
 33  * used to wait on when there are no free requests
 34  */
 35 struct wait_queue * wait_for_request = NULL;
 36 
 37 /* This specifies how many sectors to read ahead on the disk.  */
 38 
 39 int read_ahead[MAX_BLKDEV] = {0, };
 40 
 41 /* blk_dev_struct is:
 42  *      do_request-address
 43  *      next-request
 44  */
 45 struct blk_dev_struct blk_dev[MAX_BLKDEV] = {
 46         { NULL, NULL },         /* no_dev */
 47         { NULL, NULL },         /* dev mem */
 48         { NULL, NULL },         /* dev fd */
 49         { NULL, NULL },         /* dev hd */
 50         { NULL, NULL },         /* dev ttyx */
 51         { NULL, NULL },         /* dev tty */
 52         { NULL, NULL },         /* dev lp */
 53         { NULL, NULL },         /* dev pipes */
 54         { NULL, NULL },         /* dev sd */
 55         { NULL, NULL }          /* dev st */
 56 };
 57 
 58 /*
 59  * blk_size contains the size of all block-devices in units of 1024 byte
 60  * sectors:
 61  *
 62  * blk_size[MAJOR][MINOR]
 63  *
 64  * if (!blk_size[MAJOR]) then no minor size checking is done.
 65  */
 66 int * blk_size[MAX_BLKDEV] = { NULL, NULL, };
 67 
 68 /*
 69  * blksize_size contains the size of all block-devices:
 70  *
 71  * blksize_size[MAJOR][MINOR]
 72  *
 73  * if (!blksize_size[MAJOR]) then 1024 bytes is assumed.
 74  */
 75 int * blksize_size[MAX_BLKDEV] = { NULL, NULL, };
 76 
 77 /*
 78  * look for a free request in the first N entries.
 79  * NOTE: interrupts must be disabled on the way in, and will still
 80  *       be disabled on the way out.
 81  */
 82 static inline struct request * get_request(int n, int dev)
 83 {
 84         static struct request *prev_found = NULL, *prev_limit = NULL;
 85         register struct request *req, *limit;
 86 
 87         if (n <= 0)
 88                 panic("get_request(%d): impossible!\n", n);
 89 
 90         limit = all_requests + n;
 91         if (limit != prev_limit) {
 92                 prev_limit = limit;
 93                 prev_found = all_requests;
 94         }
 95         req = prev_found;
 96         for (;;) {
 97                 req = ((req > all_requests) ? req : limit) - 1;
 98                 if (req->dev < 0)
 99                         break;
100                 if (req == prev_found)
101                         return NULL;
102         }
103         prev_found = req;
104         req->dev = dev;
105         return req;
106 }
107 
108 /*
109  * wait until a free request in the first N entries is available.
110  * NOTE: interrupts must be disabled on the way in, and will still
111  *       be disabled on the way out.
112  */
113 static inline struct request * get_request_wait(int n, int dev)
114 {
115         register struct request *req;
116 
117         while ((req = get_request(n, dev)) == NULL)
118                 sleep_on(&wait_for_request);
119         return req;
120 }
121 
122 /* RO fail safe mechanism */
123 
124 static long ro_bits[MAX_BLKDEV][8];
125 
126 int is_read_only(int dev)
127 {
128         int minor,major;
129 
130         major = MAJOR(dev);
131         minor = MINOR(dev);
132         if (major < 0 || major >= MAX_BLKDEV) return 0;
133         return ro_bits[major][minor >> 5] & (1 << (minor & 31));
134 }
135 
136 void set_device_ro(int dev,int flag)
137 {
138         int minor,major;
139 
140         major = MAJOR(dev);
141         minor = MINOR(dev);
142         if (major < 0 || major >= MAX_BLKDEV) return;
143         if (flag) ro_bits[major][minor >> 5] |= 1 << (minor & 31);
144         else ro_bits[major][minor >> 5] &= ~(1 << (minor & 31));
145 }
146 
147 /*
148  * add-request adds a request to the linked list.
149  * It disables interrupts so that it can muck with the
150  * request-lists in peace.
151  */
152 static void add_request(struct blk_dev_struct * dev, struct request * req)
153 {
154         struct request * tmp;
155 
156         req->next = NULL;
157         cli();
158         if (req->bh)
159                 req->bh->b_dirt = 0;
160         if (!(tmp = dev->current_request)) {
161                 dev->current_request = req;
162                 (dev->request_fn)();
163                 sti();
164                 return;
165         }
166         for ( ; tmp->next ; tmp = tmp->next) {
167                 if ((IN_ORDER(tmp,req) ||
168                     !IN_ORDER(tmp,tmp->next)) &&
169                     IN_ORDER(req,tmp->next))
170                         break;
171         }
172         req->next = tmp->next;
173         tmp->next = req;
174 
175 /* for SCSI devices, call request_fn unconditionally */
176         if (scsi_major(MAJOR(req->dev)))
177                 (dev->request_fn)();
178 
179         sti();
180 }
181 
182 static void make_request(int major,int rw, struct buffer_head * bh)
183 {
184         unsigned int sector, count;
185         struct request * req;
186         int rw_ahead, max_req;
187 
188 /* WRITEA/READA is special case - it is not really needed, so if the */
189 /* buffer is locked, we just forget about it, else it's a normal read */
190         rw_ahead = (rw == READA || rw == WRITEA);
191         if (rw_ahead) {
192                 if (bh->b_lock)
193                         return;
194                 if (rw == READA)
195                         rw = READ;
196                 else
197                         rw = WRITE;
198         }
199         if (rw!=READ && rw!=WRITE) {
200                 printk("Bad block dev command, must be R/W/RA/WA\n");
201                 return;
202         }
203         count = bh->b_size >> 9;
204         sector = bh->b_blocknr * count;
205         if (blk_size[major])
206                 if (blk_size[major][MINOR(bh->b_dev)] < (sector + count)>>1) {
207                         bh->b_dirt = bh->b_uptodate = 0;
208                         return;
209                 }
210         lock_buffer(bh);
211         if ((rw == WRITE && !bh->b_dirt) || (rw == READ && bh->b_uptodate)) {
212                 unlock_buffer(bh);
213                 return;
214         }
215 
216 /* we don't allow the write-requests to fill up the queue completely:
217  * we want some room for reads: they take precedence. The last third
218  * of the requests are only for reads.
219  */
220         max_req = (rw == READ) ? NR_REQUEST : ((NR_REQUEST*2)/3);
221 
222 /* big loop: look for a free request. */
223 
224 repeat:
225         cli();
226 
227 /* The scsi disk drivers completely remove the request from the queue when
228  * they start processing an entry.  For this reason it is safe to continue
229  * to add links to the top entry for scsi devices.
230  */
231         if ((major == HD_MAJOR
232              || major == SCSI_DISK_MAJOR
233              || major == SCSI_CDROM_MAJOR)
234             && (req = blk_dev[major].current_request))
235         {
236                 if (major == HD_MAJOR)
237                         req = req->next;
238                 while (req) {
239                         if (req->dev == bh->b_dev &&
240                             !req->waiting &&
241                             req->cmd == rw &&
242                             req->sector + req->nr_sectors == sector &&
243                             req->nr_sectors < 254)
244                         {
245                                 req->bhtail->b_reqnext = bh;
246                                 req->bhtail = bh;
247                                 req->nr_sectors += count;
248                                 bh->b_dirt = 0;
249                                 sti();
250                                 return;
251                         }
252 
253                         if (req->dev == bh->b_dev &&

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -