]> Zhao Yanbai Git Server - kernel.git/commitdiff
在 disk_request 里添加 bbuffer 字段;将block_read 加到 bread 逻辑里;添加 brelse
authoracevest <zhaoyanbai@126.com>
Fri, 20 Oct 2023 16:06:53 +0000 (00:06 +0800)
committeracevest <zhaoyanbai@126.com>
Sat, 13 Apr 2024 08:23:58 +0000 (16:23 +0800)
drivers/ata.c
drivers/block.c
drivers/keyboard.c
fs/buffer.c
gdbscript
include/buffer.h
include/disk.h
include/wait.h
kernel/completion.c
kernel/task_disk.c
kernel/wait.c

index 6aaef8f717d1da4ea62f80eb3369bf0032b8ed24..8feb1820944385eed003fc542ed43e0c3586f15e 100644 (file)
@@ -201,19 +201,47 @@ void ide_ata_init() {
     }
 }
 
+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;
@@ -292,16 +320,6 @@ void ide_read_partions() {
     }
 }
 
-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®
index 674e57e8243f09d801f236fe555cee998dccb833..1b7b8bb8e96c61cc07afa3a86fc80e8df6e54928 100644 (file)
 #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>
@@ -38,11 +30,10 @@ void ata_read_ext2_sb() {
     // 则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,
@@ -55,6 +46,4 @@ void ata_read_ext2_sb() {
     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);
 }
index c3451b188995a7dea19a9396e2e55b1e9aaf50af..ff6aa8d7bdedfa7df2c001b908bc81111d9398bc 100644 (file)
@@ -28,8 +28,6 @@ void ide_debug();
 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[] = {
@@ -93,15 +91,6 @@ void kbd_debug(uint8_t scan_code) {
         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);
index 5d98a227b66097ed726f15bb1f37c58c4a74b809..fc98755849f8ad0926d115d73205bba7ce63434e 100644 (file)
@@ -24,6 +24,7 @@ typedef struct bbuffer_store {
     int blocksize;
     // list_head_t cache_list;
     list_head_t free_list;
+    wait_queue_head_t waitq;
 } bbuffer_store_t;
 
 // 1024, 2048, 4096
@@ -51,26 +52,29 @@ bbuffer_store_t *getstore(uint32_t size) {
 
 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);
@@ -119,7 +123,7 @@ again:
         irq_restore(iflags);
         retry++;
         // wait on free list
-        // ...
+        wait_on(&s->waitq);
         goto again;
     }
 
@@ -138,17 +142,44 @@ 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() {
@@ -170,6 +201,7 @@ 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;
@@ -191,6 +223,7 @@ void init_buffer() {
             b->page = page;
             b->uptodate = 0;
             init_completion(&b->io_done);
+            complete(&b->io_done);
             list_init(&b->node);
 
             assert(NULL != b->data);
index 7e970f0f865cd0b108641dd7afe201f41c0c3840..d5fe482a83d2fdd7f994b9c54db182fcc81ff731 100644 (file)
--- a/gdbscript
+++ b/gdbscript
@@ -8,6 +8,8 @@ set confirm off
 
 #break *0x100000
 
+b block.c:63
+#b task_disk.c:94
 
 #handle SIGINT nostop noprint
 
index c64a3a88c44aed7e7ad452f490f2d048c88afed8..b4157566900e82f4a33dfc78afbcf3bacfb70a35 100644 (file)
@@ -26,3 +26,7 @@ typedef struct bbuffer {
     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);
index 751b5c9077d84ceb096585e44f0d2a4f3f016cb0..c63d184eaa1317bb5f1889fc8d8d0f1df4271a88 100644 (file)
@@ -9,10 +9,11 @@
 
 #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,
@@ -21,9 +22,10 @@ typedef enum {
 
 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;
@@ -38,5 +40,3 @@ typedef struct {
 } 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);
index f1bf5ea0aec44592627355edcc97dac0e02e8ef5..b591ea3dd15fed942aeacad80c6a581028ab0fc7 100644 (file)
@@ -45,10 +45,15 @@ void prepare_to_wait(wait_queue_head_t *head, wait_queue_t *wq, unsigned int sta
 
 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);           \
@@ -57,6 +62,7 @@ void schedule();
             if ((condition)) {                         \
                 break;                                 \
             }                                          \
+            void schedule();                           \
             schedule();                                \
         }                                              \
         __end_wait(&__wait);                           \
@@ -68,3 +74,6 @@ void schedule();
             __wait_event(head, (condition)); \
         }                                    \
     } while (0)
+
+// 无条件wait
+void wait_on(wait_queue_head_t *head);
index 78c191c03320d389220f6ed0e910f6266bea04e8..8d2ab8b6bc68e5dc905ada2d93cf1b17fe8a602c 100644 (file)
 #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);
 }
 
index a774398a07c8f6fd95e0fc6b83b350ae5b142095..ae22190cb57b5b989bc0e917bbb8aed4b24efd96 100644 (file)
@@ -102,8 +102,13 @@ void disk_task_entry(void *arg) {
             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");
@@ -119,6 +124,11 @@ void disk_task_entry(void *arg) {
             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));
     }
index 316205e3eb2606cd3707ac09157922ab6a92c68d..0ee1d13572a74f721568c2deb60623d5f4a6ebab 100644 (file)
@@ -32,18 +32,6 @@ volatile void __end_wait(wait_queue_t *wq) {
     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);
@@ -58,79 +46,43 @@ volatile void del_wait_queue(wait_queue_head_t *head, wait_queue_t *wq) {
     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);
 }