📄 ll_rw_blk.c
字号:
unlock_buffer(bh); /* Hmmph! Already have it */ return; } kstat.pgpgin++; max_req = NR_REQUEST; /* reads take precedence */ break; case WRITEA: rw_ahead = 1; rw = WRITE; /* drop into WRITE */ case WRITE: if (!buffer_dirty(bh)) {#if 0 printk ("make_request(): buffer clean for WRITE\n");#endif unlock_buffer(bh); /* Hmmph! Nothing to write */ return; } /* We don't allow the write-requests to fill up the * queue completely: we want some room for reads, * as they take precedence. The last third of the * requests are only for reads. */ kstat.pgpgout++; max_req = (NR_REQUEST * 2) / 3; break; default: printk(KERN_ERR "make_request: bad block dev cmd," " must be R/W/RA/WA\n"); unlock_buffer(bh); return; }/* look for a free request. */ /* Loop uses two requests, 1 for loop and 1 for the real device. * Cut max_req in half to avoid running out and deadlocking. */ if (major == LOOP_MAJOR) max_req >>= 1; /* * Try to coalesce the new request with old requests */ cli(); req = blk_dev[major].current_request; if (!req) { /* MD and loop can't handle plugging without deadlocking */ if (major != MD_MAJOR && major != LOOP_MAJOR) plug_device(blk_dev + major); } else switch (major) { case IDE0_MAJOR: /* same as HD_MAJOR */ case IDE1_MAJOR: case FLOPPY_MAJOR: case IDE2_MAJOR: case IDE3_MAJOR: case XT_DISK_MAJOR: /* * The scsi disk and cdrom drivers completely remove the request * from the queue when they start processing an entry. For this * reason it is safe to continue to add links to the top entry for * those devices. * * All other drivers need to jump over the first entry, as that * entry may be busy being processed and we thus can't change it. */ req = req->next; if (!req) break; /* fall through */ case SCSI_DISK_MAJOR: case SCSI_CDROM_MAJOR: do { if (req->sem) continue; if (req->cmd != rw) continue; if (req->nr_sectors >= MAX_SECTORS) continue; if (req->rq_dev != bh->b_rdev) continue; /* Can we add it to the end of this request? */ if (req->sector + req->nr_sectors == sector) { req->bhtail->b_reqnext = bh; req->bhtail = bh; req->nr_sectors += count; /* Can we now merge this req with the next? */ attempt_merge(req); /* or to the beginning? */ } else if (req->sector - count == sector) { bh->b_reqnext = req->bh; req->bh = bh; req->buffer = bh->b_data; req->current_nr_sectors = count; req->sector = sector; req->nr_sectors += count; } else continue; mark_buffer_clean(bh); sti(); return; } while ((req = req->next) != NULL); }/* find an unused request. */ req = get_request(max_req, bh->b_rdev); sti();/* if no request available: if rw_ahead, forget it; otherwise try again blocking.. */ if (!req) { if (rw_ahead) { unlock_buffer(bh); return; } req = __get_request_wait(max_req, bh->b_rdev); }/* fill up the request-info, and add it to the queue */ req->cmd = rw; req->errors = 0; req->sector = sector; req->nr_sectors = count; req->current_nr_sectors = count; req->buffer = bh->b_data; req->sem = NULL; req->bh = bh; req->bhtail = bh; req->next = NULL; add_request(major+blk_dev,req);}/* This function can be used to request a number of buffers from a block device. Currently the only restriction is that all buffers must belong to the same device */void ll_rw_block(int rw, int nr, struct buffer_head * bh[]){ unsigned int major; int correct_size; struct blk_dev_struct * dev; int i; /* Make sure that the first block contains something reasonable */ while (!*bh) { bh++; if (--nr <= 0) return; } dev = NULL; if ((major = MAJOR(bh[0]->b_dev)) < MAX_BLKDEV) dev = blk_dev + major; if (!dev || !dev->request_fn) { printk(KERN_ERR "ll_rw_block: Trying to read nonexistent block-device %s (%ld)\n", kdevname(bh[0]->b_dev), bh[0]->b_blocknr); goto sorry; } /* Determine correct block size for this device. */ correct_size = BLOCK_SIZE; if (blksize_size[major]) { i = blksize_size[major][MINOR(bh[0]->b_dev)]; if (i) correct_size = i; } /* Verify requested block sizes. */ for (i = 0; i < nr; i++) { if (bh[i] && bh[i]->b_size != correct_size) { printk(KERN_NOTICE "ll_rw_block: device %s: " "only %d-char blocks implemented (%lu)\n", kdevname(bh[0]->b_dev), correct_size, bh[i]->b_size); goto sorry; } /* Md remaps blocks now */ bh[i]->b_rdev = bh[i]->b_dev; bh[i]->b_rsector=bh[i]->b_blocknr*(bh[i]->b_size >> 9);#ifdef CONFIG_BLK_DEV_MD if (major==MD_MAJOR && md_map (MINOR(bh[i]->b_dev), &bh[i]->b_rdev, &bh[i]->b_rsector, bh[i]->b_size >> 9)) { printk (KERN_ERR "Bad md_map in ll_rw_block\n"); goto sorry; }#endif } if ((rw == WRITE || rw == WRITEA) && is_read_only(bh[0]->b_dev)) { printk(KERN_NOTICE "Can't write to read-only device %s\n", kdevname(bh[0]->b_dev)); goto sorry; } for (i = 0; i < nr; i++) { if (bh[i]) { set_bit(BH_Req, &bh[i]->b_state);#ifdef CONFIG_BLK_DEV_MD if (MAJOR(bh[i]->b_dev) == MD_MAJOR) { md_make_request(MINOR (bh[i]->b_dev), rw, bh[i]); continue; }#endif make_request(MAJOR(bh[i]->b_rdev), rw, bh[i]); } } return; sorry: for (i = 0; i < nr; i++) { if (bh[i]) { clear_bit(BH_Dirty, &bh[i]->b_state); clear_bit(BH_Uptodate, &bh[i]->b_state); } } return;}void ll_rw_swap_file(int rw, kdev_t dev, unsigned int *b, int nb, char *buf){ int i, j; int buffersize; int max_req; unsigned long rsector; kdev_t rdev; struct request * req[8]; unsigned int major = MAJOR(dev); struct semaphore sem = MUTEX_LOCKED; if (major >= MAX_BLKDEV || !(blk_dev[major].request_fn)) { printk(KERN_NOTICE "ll_rw_swap_file: trying to swap to" " nonexistent block-device\n"); return; } max_req = NR_REQUEST; switch (rw) { case READ: break; case WRITE: max_req = (NR_REQUEST * 2) / 3; if (is_read_only(dev)) { printk(KERN_NOTICE "Can't swap to read-only device %s\n", kdevname(dev)); return; } break; default: panic("ll_rw_swap: bad block dev cmd, must be R/W"); } buffersize = PAGE_SIZE / nb; if (major == LOOP_MAJOR) max_req >>= 1; for (j=0, i=0; i<nb;) { for (; j < 8 && i < nb; j++, i++, buf += buffersize) { rdev = dev; rsector = b[i] * (buffersize >> 9);#ifdef CONFIG_BLK_DEV_MD if (major==MD_MAJOR && md_map (MINOR(dev), &rdev, &rsector, buffersize >> 9)) { printk (KERN_ERR "Bad md_map in ll_rw_swap_file\n"); return; }#endif if (j == 0) { req[j] = get_request_wait(max_req, rdev); } else { cli(); req[j] = get_request(max_req, rdev); sti(); if (req[j] == NULL) break; } req[j]->cmd = rw; req[j]->errors = 0; req[j]->sector = rsector; req[j]->nr_sectors = buffersize >> 9; req[j]->current_nr_sectors = buffersize >> 9; req[j]->buffer = buf; req[j]->sem = &sem; req[j]->bh = NULL; req[j]->next = NULL; add_request(MAJOR(rdev)+blk_dev,req[j]); } run_task_queue(&tq_disk); while (j > 0) { j--; down(&sem); } }}int blk_dev_init(void){ struct request * req; struct blk_dev_struct *dev; for (dev = blk_dev + MAX_BLKDEV; dev-- != blk_dev;) { dev->request_fn = NULL; dev->current_request = NULL; dev->plug.rq_status = RQ_INACTIVE; dev->plug.cmd = -1; dev->plug.next = NULL; dev->plug_tq.routine = &unplug_device; dev->plug_tq.data = dev; } req = all_requests + NR_REQUEST; while (--req >= all_requests) { req->rq_status = RQ_INACTIVE; req->next = NULL; } memset(ro_bits,0,sizeof(ro_bits));#ifdef CONFIG_BLK_DEV_RAM rd_init();#endif#ifdef CONFIG_BLK_DEV_LOOP loop_init();#endif#ifdef CONFIG_BLK_DEV_IDE ide_init(); /* this MUST precede hd_init */#endif#ifdef CONFIG_BLK_DEV_HD hd_init();#endif#ifdef CONFIG_BLK_DEV_XD xd_init();#endif#ifdef CONFIG_BLK_DEV_FD floppy_init();#else#if !defined(CONFIG_ARCH_ARC) && !defined(CONFIG_ARCH_SA110EVAL) outb_p(0xc, 0x3f2);#endif#endif#ifdef CONFIG_BLK_DEV_MD md_init();#endif CONFIG_BLK_DEV_MD return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -