}
}
+void ide_disk_read(dev_t dev, uint32_t sect_nr, uint32_t count, bbuffer_t *b) {
+ disk_request_t r;
+ r.dev = dev;
+ r.command = DISK_REQ_READ;
+ r.pos = sect_nr;
+ r.count = count;
+ r.buf = NULL;
+ r.bb = b;
+ send_disk_request(&r);
+}
+
+void tmp_ide_disk_read(dev_t dev, uint32_t sect_nr, uint32_t count, char *buf) {
+ disk_request_t r;
+ r.dev = dev;
+ r.command = DISK_REQ_READ;
+ r.pos = sect_nr;
+ r.count = count;
+ r.buf = buf;
+ r.bb = NULL;
+ send_disk_request(&r);
+}
+
// mbr_ext_offset: 在MBR中的扩展分区记录里的偏移地址
// lba_partition_table: 扩展分区的真实偏移地址
void read_partition_table(ide_drive_t *drv, uint32_t mbr_ext_offset, uint32_t lba_partition_table, int depth) {
disk_request_t r;
char *sect = kmalloc(SECT_SIZE, 0);
+#if 1
+ // part_no == 0 代表整场硬盘
+ tmp_ide_disk_read(MAKE_DISK_DEV(drv->drv_no, 0), lba_partition_table, 1, sect);
+#else
// part_no == 0 代表整场硬盘
r.dev = MAKE_DISK_DEV(drv->drv_no, 0);
r.command = DISK_REQ_READ;
r.pos = lba_partition_table;
r.count = 1;
r.buf = sect;
+ r.bb = NULL;
send_disk_request(&r);
+#endif
ide_part_t *part = 0;
uint32_t part_id = 0;
}
}
-void ide_disk_read(dev_t dev, uint32_t sect_nr, uint32_t count, char *buf) {
- disk_request_t r;
- r.dev = dev;
- r.command = DISK_REQ_READ;
- r.pos = sect_nr;
- r.count = count;
- r.buf = buf;
- send_disk_request(&r);
-}
-
// ATA_CMD_READ_DMA_EXT
void ata_dma_read_ext(int drv, uint64_t pos, uint16_t count, void *dest) {
// Intel®
#include <fs.h>
#include <ide.h>
-bbuffer_t *block_read(dev_t dev, uint32_t block) {
- bbuffer_t *bb = 0;
-
- assert(DEV_MAJOR(dev) == DEV_MAJOR_DISK);
- // assert(DEV_MINOR(dev) == 1);
-
- // 目前不提供hash表组强起来的缓冲功能
- // 直接读
-
- // TODO:根据dev得到正确的blocksize
- const int blocksize = 1024;
-
- bb->data = kmalloc(blocksize, 0); // debug
-
- ide_disk_read(dev, block * blocksize / 512, 1, bb->data);
-
- return bb;
+void ide_disk_read(dev_t dev, uint32_t sect_nr, uint32_t count, bbuffer_t *b);
+void block_read(bbuffer_t *b) {
+ assert(b != NULL);
+ assert(b->data != NULL);
+ assert(b->page != NULL);
+ assert(DEV_MAJOR(b->dev) == DEV_MAJOR_DISK);
+ assert(b->block_size != 0);
+
+ ide_disk_read(b->dev, (b->block * b->block_size) / 512, b->block_size / 512, b);
}
#include <ext2.h>
// 则ext2_superblock应该在第1个block的offset为0的位置
// ext2_superblock默认大小1024
- const int offset = 0;
- const int size = offset + 1024;
- const int block = 1;
-
- bbuffer_t *bb = block_read(system.root_dev, block);
+ const int block = 0;
+ const int offset = 1024;
+ const int size = 4096;
+ bbuffer_t *bb = bread(system.root_dev, block, size);
ext2_sb_t *p = (ext2_sb_t *)(bb->data + offset);
printk("inodes count %u inodes per group %u free %u\n", p->s_inodes_count, p->s_inodes_per_group,
strncpy(volume_name, p->s_volume_name, 16);
volume_name[16] = 0;
printk("volume %s\n", volume_name);
- // printk("last mounted %s\n", p->s_last_mounted);
- kfree(bb->data);
}
void ide_status();
void debug_sched();
-int debug_wait_queue_put(unsigned int v);
-
void kbd_debug(uint8_t scan_code);
char kbd_char_tbl[] = {
tty_switch(debug_tty);
}
- if (scan_code == 0x3F) // F5
- debug_wait_queue_put(0);
- if (scan_code == 0x40) // F6
- debug_wait_queue_put(1);
- if (scan_code == 0x41) // F7
- debug_wait_queue_put(2);
- if (scan_code == 0x42) // F8
- debug_wait_queue_put(7);
-
if (scan_code == 0x43) { // F9
void ata_test(uint64_t nr);
ata_test(0);
int blocksize;
// list_head_t cache_list;
list_head_t free_list;
+ wait_queue_head_t waitq;
} bbuffer_store_t;
// 1024, 2048, 4096
bbuffer_t *get_from_hash_table(dev_t dev, uint64_t block, uint32_t size) {
list_head_t *p = 0;
+ bbuffer_t *b = 0;
+
uint32_t hash = hashfn(dev, block);
assert(hash < BLOCK_BUFFER_HASH_TABLE_SIZE);
list_for_each(p, block_buffer_hash_table + hash) {
- bbuffer_t *b = list_entry(p, bbuffer_t, node);
- if (b->dev != dev) {
+ bbuffer_t *t = list_entry(p, bbuffer_t, node);
+ if (t->dev != dev) {
continue;
}
- if (b->block != block) {
+ if (t->block != block) {
continue;
}
- assert(b->block_size == size);
+ assert(t->block_size == size);
+
+ b = t;
break;
}
// 如果找到了就直接返回
- if (0 != p) {
- bbuffer_t *b = list_entry(p, bbuffer_t, node);
+ if (b != NULL) {
atomic_inc(&b->ref_count);
assert(0 != b);
assert(0 != b->data);
irq_restore(iflags);
retry++;
// wait on free list
- // ...
+ wait_on(&s->waitq);
goto again;
}
b->ref_count = 1;
b->uptodate = 0;
- list_init(&b->node);
+ return b;
+}
- irq_restore(iflags);
+void brelse(bbuffer_t *b) {
+ assert(b != NULL);
+ assert(b->ref_count > 0);
- return b;
+ wait_completion(&b->io_done);
+
+ bbuffer_store_t *s = getstore(b->block_size);
+ assert(s != NULL);
+ assert(s - store < 3);
+
+ wake_up(&s->waitq);
}
bbuffer_t *bread(dev_t dev, uint64_t block, uint32_t size) {
bbuffer_t *b = getblk(dev, block, size);
- return b;
+ assert(b != NULL);
+
+ if (b->uptodate == 1) {
+ return b;
+ }
+
+ // READ
+ void block_read(bbuffer_t * b);
+ block_read(b);
+
+ // 等待I/O结束
+ wait_completion(&b->io_done);
+ if (b->uptodate == 1) {
+ return b;
+ }
+
+ brelse(b);
+
+ return NULL;
}
void init_buffer() {
store[i].blocksize = blocksize;
// list_init(&store[i].cache_list);
list_init(&store[i].free_list);
+ init_wait_queue_head(&store[i].waitq);
int page_left_space = 0;
void *data = NULL;
b->page = page;
b->uptodate = 0;
init_completion(&b->io_done);
+ complete(&b->io_done);
list_init(&b->node);
assert(NULL != b->data);
#break *0x100000
+b block.c:63
+#b task_disk.c:94
#handle SIGINT nostop noprint
uint16_t block_size; // block size
uint16_t uptodate : 1;
} bbuffer_t;
+
+bbuffer_t *bread(dev_t dev, uint64_t block, uint32_t size);
+
+void brelse(bbuffer_t *b);
#pragma once
+#include <buffer.h>
#include <completion.h>
+#include <fs.h>
#include <list.h>
#include <semaphore.h>
-#include <types.h>
typedef enum {
DISK_REQ_IDENTIFY,
typedef struct disk_request {
dev_t dev;
- uint64_t pos; // 扇区号
- uint16_t count; // 扇区数
- void *buf; // 到的缓冲区
+ uint64_t pos; // 扇区号
+ uint16_t count; // 扇区数
+ void *buf; // 到的缓冲区
+ bbuffer_t *bb;
disk_request_cmd_t command; // 命令
list_head_t list;
semaphore_t sem;
} disk_request_queue_t;
void send_disk_request(disk_request_t *r);
-
-void ide_disk_read(dev_t dev, uint32_t sect_nr, uint32_t count, char *buf);
void __end_wait(wait_queue_t *wq);
-// void sleep_on(wait_queue_head_t *head);
+// 使用这个函数的时候需要注意
+// 设置condition为真的语句和wake_up原子地执行
void wake_up(wait_queue_head_t *head);
+void __wake_up(wait_queue_head_t *head, int nr);
-void schedule();
+// 只要保证condition设置为真时,它是和wake_up一起原子执行的
+// 那就能保证condition为真是如下__wait_event和wait_event里的if不出问题
+// 也就是不会出现if-break后进程又再次因为其它原因阻塞后,又被wake_up的逻辑
+// 设置为READY状态
#define __wait_event(head, condition) \
do { \
DECLARE_WAIT_QUEUE(__wait, current); \
if ((condition)) { \
break; \
} \
+ void schedule(); \
schedule(); \
} \
__end_wait(&__wait); \
__wait_event(head, (condition)); \
} \
} while (0)
+
+// 无条件wait
+void wait_on(wait_queue_head_t *head);
#include <completion.h>
#include <sched.h>
-void wait_completion(completion_t *x) { wait_event(&x->wait, (x->done == 1)); }
+void wait_completion(completion_t *x) {
+ //
+ wait_event(&x->wait, (x->done == 1));
+}
void complete(completion_t *x) {
uint32_t iflags;
irq_save(iflags);
x->done = 1;
- wake_up(&x->wait);
+ // wake_up(&x->wait);
+ __wake_up(&x->wait, 0);
irq_restore(iflags);
}
break;
case DISK_REQ_READ:
assert(r->count > 0);
- assert(r->buf != NULL);
- ata_dma_read_ext(drv_no, pos, r->count, r->buf);
+ assert(r->buf != NULL || r->bb->data != NULL);
+ // printk("DISK READ drv_no %u pos %u count %u\n", drv_no, (uint32_t)pos, r->count);
+ if (r->bb != 0) {
+ ata_dma_read_ext(drv_no, pos, r->count, r->bb->data);
+ } else {
+ ata_dma_read_ext(drv_no, pos, r->count, r->buf);
+ }
break;
default:
panic("invalid disk request command");
ata_pio_read_data(drv_no, 1, r->buf);
}
+ if (r->bb != 0) {
+ r->bb->uptodate = 1;
+ complete(&r->bb->io_done);
+ }
+
// 唤醒等待该请求的进程
up(&(r->sem));
}
irq_restore(flags);
}
-volatile void wake_up(wait_queue_head_t *head) {
- unsigned long flags;
- wait_queue_t *p, *tmp;
- irq_save(flags);
- list_for_each_entry_safe(p, tmp, &head->task_list, task_list) {
- list_del(&p->task_list);
- // printk("wakeup: %s\n", p->task->name);
- p->task->state = TASK_READY;
- }
- irq_restore(flags);
-}
-
volatile void add_wait_queue(wait_queue_head_t *head, wait_queue_t *wq) {
unsigned long flags;
irq_save(flags);
irq_restore(flags);
}
-// volatile void sleep_on(wait_queue_head_t *head) {
-// DECLARE_WAIT_QUEUE(wait, current);
-
-// unsigned long flags;
-// irq_save(flags);
-
-// current->state = TASK_WAIT;
-// current->reason = "sleep_on";
-
-// list_add_tail(&wait.task_list, &head->task_list);
-
-// irq_restore(flags);
-
-// schedule();
-
-// // wake_up操作会把wait从heat链表上删除
-// // 所以这里就不用做什么了
-// }
-
-// volatile void __wake_up(wait_queue_head_t *head, int nr) {
-// unsigned long flags;
-// wait_queue_t *p, *tmp;
-// irq_save(flags);
-// list_for_each_entry_safe(p, tmp, &head->task_list, task_list) {
-// list_del(&p->task_list);
-// // printk("wakeup: %s\n", p->task->name);
-// p->task->state = TASK_READY;
-// current->reason = "wake_up";
-
-// --nr;
-// if (nr == 0) {
-// break;
-// }
-// }
-// irq_restore(flags);
+volatile void __wake_up(wait_queue_head_t *head, int nr) {
+ unsigned long flags;
+ wait_queue_t *p, *tmp;
+ irq_save(flags);
+ list_for_each_entry_safe(p, tmp, &head->task_list, task_list) {
+ p->task->state = TASK_READY;
+ current->reason = "wake_up";
-// // no schedule() here.
-// }
+ --nr;
+ if (nr == 0) {
+ break;
+ }
+ }
+ irq_restore(flags);
-// volatile void wake_up(wait_queue_head_t *head) { __wake_up(head, 1); }
+ // no schedule() here.
+}
-// #include <irq.h>
-// DECLARE_WAIT_QUEUE_HEAD(debug_wq);
-// unsigned int debug_global_var = 0;
-// int debug_wait_queue_get() {
-// unsigned int v = 0;
-// task_union *task = current;
-// DECLARE_WAIT_QUEUE(wait, task);
-// add_wait_queue(&debug_wq, &wait);
+volatile void wake_up(wait_queue_head_t *head) {
+ //
+ __wake_up(head, 1);
+}
-// while (1) {
-// printd("pid %d is going to wait\n", sysc_getpid());
-// task->state = TASK_WAIT;
+volatile void wait_on(wait_queue_head_t *head) {
+ DECLARE_WAIT_QUEUE(wait, current);
-// disable_irq();
-// v = debug_global_var;
-// if (debug_global_var != 0) debug_global_var--;
-// enable_irq();
+ unsigned long flags;
+ irq_save(flags);
-// if (v != 0) break;
+ current->state = TASK_WAIT;
+ current->reason = "sleep_on";
-// schedule();
-// printd("pid %d is running\n", sysc_getpid());
-// }
+ list_add_tail(&wait.task_list, &head->task_list);
-// printd("pid %d is really running\n", sysc_getpid());
-// task->state = TASK_READY;
-// del_wait_queue(&debug_wq, &wait);
+ irq_restore(flags);
-// return v;
-// }
+ schedule();
-int debug_wait_queue_put(unsigned int v) {
- // debug_global_var = v;
- // wake_up(&debug_wq);
+ __end_wait(&wait);
}