How does Linux md driver write data to SATA disk?

1k views Asked by At

In an Intel white paper, it says:

MD RAID in linux is a block driver that filters data between the Linux File System driver, such as ext2 file system, and the low level hard disk drivers, such as the AHCI driver and SAS driver.

In kernel code drivers/md/md.c, I only find this file_operations:

static const struct file_operations md_seq_fops = {
    .owner          = THIS_MODULE,
    .open           = md_seq_open,
    .read           = seq_read,
    .llseek         = seq_lseek,
    .release        = seq_release_private,
    .poll           = mdstat_poll,

};

md_fops has neither read nor write:

static const struct block_device_operations md_fops =
{
        .owner          = THIS_MODULE,
        .open           = md_open,
        .release        = md_release,
        .ioctl          = md_ioctl,
#ifdef CONFIG_COMPAT
        .compat_ioctl   = md_compat_ioctl,
#endif
        .getgeo         = md_getgeo,
        .media_changed  = md_media_changed,
        .revalidate_disk= md_revalidate,
};

Is this the file_operations that MD driver performs open, read...? How does MD driver writes data? Use AHCI driver?

When a write syscall is called, what is the steps to write data?

sys_write -> vfs_write -> file->f_op->write or do_sync_write? The md_seq_fops has neither write nor aio_write

2

There are 2 answers

1
MSalters On

struct file_operations has many more members. Per C99, members not listed are initialized to NULL which means they're not specially implemented. That's normal for filter drivers; they replace only some operations.

2
pratik On

The exact sequence of function calls will depend on various situations like whether I/O is direct or not, whether I/O is synchronous or asynchronous etc. Depending on these situations, at the end make_request() method of MD layer is called and this method is registered by MD layer itself at the time of RAID device creation by blk_queue_make_request() call as shown below in md.c file:

blk_queue_make_request(mddev->queue, md_make_request);

This md_make_request() function will internally calls make_request() method specific to that RAID device personality as shown below:

mddev->pers->make_request(mddev, bio);

You can find specific make_request() method in the list of RAID personality methods given in individual RAID files in source code, i.e., for raid0 personality, here is list of methods where make_request is initialized with raid0_make_request() in raid0.c file.

static struct md_personality raid0_personality=
{
         .name           = "raid0",
         .level          = 0,
         .owner          = THIS_MODULE,
         .make_request   = raid0_make_request,
         .run            = raid0_run,
         .free           = raid0_free,
         .status         = raid0_status,
         .size           = raid0_size,
         .takeover       = raid0_takeover,
         .quiesce        = raid0_quiesce,
         .congested      = raid0_congested,
};

This raid0_make_request() function will perform read or write on raid0 device.