首页 > 解决方案 > Linux Kernel vfs_write 函数混淆

问题描述

我正在查看旧的 Linux 内核代码(3.10.1),尤其是 IO 路径。

所以当IO进入VFS层时,该函数vfs_write()被调用。

在这里,我可以看到对 的调用file->f_op->write(),正如系统调用的手册页所述,这是一个阻塞调用write()

代码中的另一个选项file->f_op->write是未定义指针时,在这种情况下vfs_write()调用do_sync_write().

do_sync_write()继续并调用filp->f_op->aio_write(),这是一个异步调用,正如手册页所aio_write()解释的那样。

现在,我的问题是,为什么函数do_sync_write()命名为“sync”,而它显然继续调用异步 IO 函数?

我可能会遗漏一些东西,或者那个时候在这里犯了一个错误?

函数定义供参考,

ssize_t vfs_write(struct file *file, const char __user *buf, size_t count, loff_t *pos)
{
    ssize_t ret;

    if (!(file->f_mode & FMODE_WRITE))
        return -EBADF;
    if (!file->f_op || (!file->f_op->write && !file->f_op->aio_write))
        return -EINVAL;
    if (unlikely(!access_ok(VERIFY_READ, buf, count)))
        return -EFAULT;

    ret = rw_verify_area(WRITE, file, pos, count);
        if (ret >= 0) {
        count = ret;
        file_start_write(file);
        if (file->f_op->write)
            ret = file->f_op->write(file, buf, count, pos);
        else
            ret = do_sync_write(file, buf, count, pos);
        if (ret > 0) {
            fsnotify_modify(file);
            add_wchar(current, ret);
        }
        inc_syscw(current);
        file_end_write(file);
    }

    return ret;
}



ssize_t do_sync_write(struct file *filp, const char __user *buf, size_t len, loff_t *ppos)
{
    struct iovec iov = { .iov_base = (void __user *)buf, .iov_len = len };
    struct kiocb kiocb;
    ssize_t ret;

    init_sync_kiocb(&kiocb, filp);
    kiocb.ki_pos = *ppos;
    kiocb.ki_left = len;
    kiocb.ki_nbytes = len;

    ret = filp->f_op->aio_write(&kiocb, &iov, 1, kiocb.ki_pos);
    if (-EIOCBQUEUED == ret)
        ret = wait_on_sync_kiocb(&kiocb);
    *ppos = kiocb.ki_pos;
    return ret;
}

标签: clinuxlinux-kernelfilesystemsvfs

解决方案


为什么该函数do_sync_write()被命名为“sync”,而它显然继续调用异步 IO 函数?

它调用异步函数,然后等待其完成

ret = wait_on_sync_kiocb(&kiocb);

所以从函数调用者的角度来看do_sync_write,整个函数的行为是同步的。


推荐阅读