linux-kerneloperating-systeminterruptdisk-io

What does the Linux 0.11 kernel do while the disk prepares data after hd_out?


I’m exploring the Linux 0.11 source code, specifically how it reads data from the disk into memory. I’ve been analyzing the hd_out function and the associated do_hd_request in hd.c.

Here’s the relevant code snippet:

#define CURRENT (blk_dev[MAJOR_NR].current_request)

// hd.c
void do_hd_request(void) {
    ...
    unsigned int dev = MINOR(CURRENT->dev);
    unsigned int block = CURRENT->sector;
    ...
    nsect = CURRENT->nr_sectors;
    ...
    if (CURRENT->cmd == WRITE) {
        hd_out(dev, nsect, sec, head, cyl, WIN_WRITE, &write_intr);
        // Poll status register to check if ready to write
        for (i = 0; i < 3000 && !(r = inb_p(HD_STATUS) & DRQ_STAT); i++);
        if (!r) {
            bad_rw_intr();
            goto repeat;
        }
        port_write(HD_DATA, CURRENT->buffer, 256);
    } else if (CURRENT->cmd == READ) {
        hd_out(dev, nsect, sec, head, cyl, WIN_READ, &read_intr);
    } else
        panic("unknown hd-command");
}

static void hd_out(unsigned int drive, unsigned int nsect, unsigned int sect,
                   unsigned int head, unsigned int cyl, unsigned int cmd,
                   void (*intr_addr)(void)) {
    ...
    do_hd = intr_addr;
    outb_p(hd_info[drive].ctl, HD_CMD);
    port = HD_DATA;
    outb_p(hd_info[drive].wpcom >> 2, ++port);
    outb_p(nsect, ++port);
    outb_p(sect, ++port);
    outb_p(cyl, ++port);
    outb_p(cyl >> 8, ++port);
    outb_p(0xA0 | (drive << 4) | head, ++port);
    outb(cmd, ++port);
}

From my understanding, hd_out issues the command to the disk and assigns the appropriate interrupt handler (e.g., read_intr or write_intr). The disk then starts preparing the data. My question is: What does the kernel do while the disk is preparing data?

I assume the kernel should switch to another process (via a timer interrupt or similar mechanism), but when I debugged the process, I noticed that after hd_out, the next instruction executed is the disk interrupt handler (e.g., hd_interrupt), suggesting the disk was ready immediately. This behavior seems strange because I expected a process switch during the disk preparation time.

Any clarification on this behavior would be greatly appreciated!


Solution

  • It switches to a different process.

    The thing you are missing is: there exists a request queue. When a process reads or writes, it doesn't directly call do_hd_request(). Instead, it puts its request onto a queue, and then goes to sleep. It only calls do_hd_request() if the queue is empty.

    When a disk operation completes, the disk interrupt marks the request as complete, wakes up processes waiting on it, and then issues the next request from the queue. So, unless the queue is empty, your request is issued by a interrupt handler on completing the previous request. That's why do_hd_request() is called from hd_interrupt.

    Relevant code: