美文网首页
浅尝辄止86-NTFS文件系统1-内核2-读文件0

浅尝辄止86-NTFS文件系统1-内核2-读文件0

作者: 阿棍儿_Leon | 来源:发表于2019-03-01 20:59 被阅读0次

与FAT32一样,NTFS也有自己的构建inode的方法,这点也没什么好说的,就是一个生成文件编号的算法,只要不重复,怎么生都行。
写文件也是类似的,也是先如page,然后再由后备设备刷到磁盘上。
在NTFS文件系统上就看看怎么读吧,因为它的写功能通常是关闭的,开起来能不能用也不知道。

读文件

了解文件操作,关键点是文件系统的struct file_operations变量的赋值。NTFS的在kernel/fs/ntfs/file.cntfs_file_open里面也是接到VFS的open,NTFS关于open的自定义操作很少,就不研究了。

const struct file_operations ntfs_file_ops = {
    .llseek     = generic_file_llseek,   /* Seek inside file. */
    .read       = new_sync_read,     /* Read from file. */
    .read_iter  = generic_file_read_iter, /* Async read from file. */
#ifdef NTFS_RW
    .write      = do_sync_write,     /* Write to file. */
    .aio_write  = ntfs_file_aio_write,   /* Async write to file. */
    /*.release  = ,*/            /* Last file is closed.  See
                            fs/ext2/file.c::
                            ext2_release_file() for
                            how to use this to discard
                            preallocated space for
                            write opened files. */
    .fsync      = ntfs_file_fsync,   /* Sync a file to disk. */
    /*.aio_fsync    = ,*/            /* Sync all outstanding async
                            i/o operations on a
                            kiocb. */
#endif /* NTFS_RW */
    /*.ioctl    = ,*/            /* Perform function on the
                            mounted filesystem. */
    .mmap       = generic_file_mmap,     /* Mmap file. */
    .open       = ntfs_file_open,    /* Open file. */
    .splice_read    = generic_file_splice_read /* Zero-copy data send with
                            the data source being on
                            the ntfs partition.  We do
                            not need to care about the
                            data destination. */
    /*.sendpage = ,*/            /* Zero-copy data send with
                            the data destination being
                            on the ntfs partition.  We
                            do not need to care about
                            the data source. */
};

new_sync_read是读操作,仔细看一下可知,它实际上用filp->f_op->read_iter调用的是.read_iter=generic_file_read_iter这个函数。

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

    init_sync_kiocb(&kiocb, filp);
    kiocb.ki_pos = *ppos;
    kiocb.ki_nbytes = len;
    iov_iter_init(&iter, READ, &iov, 1, len);

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

然后到do_generic_file_read里面的copy_page_to_iter,一个page就被拷贝到用户的buffer了。
当然,在此之前要先readpage,要让page的内容与磁盘内容一致,这样拷贝给用户的才是磁盘内容。readpage的出发点当然在do_generic_file_read里面,但是我们其实可以不分析这里,因为关于文件的page操作每个文件系统都要定义清楚,不管这个函数怎么执行,都要调用到那些操作。与FAT32类似,那些操作就是一个struct address_space_operations变量,就是const struct address_space_operations ntfs_normal_aops,在kernel/fs/ntfs/aops.c

const struct address_space_operations ntfs_normal_aops = {
    .readpage   = ntfs_readpage,
#ifdef NTFS_RW
    .writepage  = ntfs_writepage,
    .set_page_dirty = __set_page_dirty_buffers,
#endif /* NTFS_RW */
    .bmap       = ntfs_bmap,
    .migratepage    = buffer_migrate_page,
    .is_partially_uptodate = block_is_partially_uptodate,
    .error_remove_page = generic_error_remove_page,
};

下次我们要分析一下ntfs_readpage这个函数。

相关文章

网友评论

      本文标题:浅尝辄止86-NTFS文件系统1-内核2-读文件0

      本文链接:https://www.haomeiwen.com/subject/xyhduqtx.html