测试用例:
#include <stdio.h>
#include <fcntl.h>
#include <linux/hdreg.h>
#include <sys/ioctl.h>
#include <string.h>
#include <unistd.h>
static void dump_identity (const struct hd_driveid *id);
int main(void)
{
int fd = 0;
unsigned char buf[512];
fd = open("/dev/sda",O_RDONLY);
static struct hd_driveid id;
if (!ioctl(fd, HDIO_GET_IDENTITY, &id))
{
dump_identity(&id);
}
else
{
printf(" HDIO_GET_IDENTITY failed\n");
perror("ioctl:");
}
memset(buf, 0x00, 512);
if(read(fd, buf, 512) != 512)
{
perror("read error.\n");
}
return 0;
}
static void dump_identity (const struct hd_driveid *id)
{
const unsigned short int *id_regs= (const void*) id;
printf("Model=%.40s, FwRev=%.8s, SerialNo=%.20s\n", id->model, id->fw_rev, id->serial_no);
}
内核加入log:
diff --git a/fs/block_dev.c b/fs/block_dev.c
index fa329c7ed..b0dcdb0b0 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -2034,6 +2034,10 @@ ssize_t blkdev_read_iter(struct kiocb *iocb, struct iov_iter *to)
if (pos >= size)
return 0;
+ if(!strcmp("blktest", current->comm))
+ {
+ printk("%s line %d.\n", __func__, __LINE__);
+ }
size -= pos;
if (iov_iter_count(to) > size) {
shorted = iov_iter_count(to) - size;
diff --git a/fs/read_write.c b/fs/read_write.c
index 7458fccc5..672e0bae1 100644
--- a/fs/read_write.c
+++ b/fs/read_write.c
@@ -421,6 +421,11 @@ static ssize_t new_sync_read(struct file *filp, char __user *buf, size_t len, lo
ssize_t __vfs_read(struct file *file, char __user *buf, size_t count,
loff_t *pos)
{
+ if(!strcmp("blktest", current->comm))
+ {
+ printk("%s line %d, read = 0x%lx. read_iter = 0x%lx.\n", __func__, __LINE__, (unsigned long)file->f_op->read, (unsigned long)file->f_op->read_iter);
+ }
+
if (file->f_op->read)
return file->f_op->read(file, buf, count, pos);
else if (file->f_op->read_iter)
@@ -447,6 +452,7 @@ ssize_t vfs_read(struct file *file, char __user *buf, size_t count, loff_t *pos)
{
ssize_t ret;
+
if (!(file->f_mode & FMODE_READ))
return -EBADF;
if (!(file->f_mode & FMODE_CAN_READ))
diff --git a/mm/filemap.c b/mm/filemap.c
index c10e237cc..916c325af 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -2050,6 +2050,11 @@ static ssize_t generic_file_buffered_read(struct kiocb *iocb,
last_index = (*ppos + iter->count + PAGE_SIZE-1) >> PAGE_SHIFT;
offset = *ppos & ~PAGE_MASK;
+ if(!strcmp("blktest", current->comm))
+ {
+ printk("%s line %d.\n", __func__, __LINE__);
+ }
+
for (;;) {
struct page *page;
pgoff_t end_index;
[点击并拖拽以移动]
执行后:
caozilong@caozilong-Vostro-3268:~/Workspace/identiy$ ls
blktest main.c
caozilong@caozilong-Vostro-3268:~/Workspace/identiy$ sudo ./blktest
Model=Samsung SSD 860 EVO 500GB , FwRev=RVT02B6Q, SerialNo=S3Z3NB0M420385X
caozilong@caozilong-Vostro-3268:~/Workspace/identiy$
dmesg有如下log输出:
[ 12.556973] IPv6: ADDRCONF(NETDEV_CHANGE): enp2s0: link becomes ready
[ 19.604621] Bluetooth: RFCOMM TTY layer initialized
[ 19.604625] Bluetooth: RFCOMM socket layer initialized
[ 19.604631] Bluetooth: RFCOMM ver 1.11
[ 20.405604] rfkill: input handler disabled
[ 57.135125] __vfs_read line 426, read = 0x0. read_iter = 0xffffffffa279aea0.
[ 57.135128] generic_file_buffered_read line 2055.
[ 57.135567] __vfs_read line 426, read = 0x0. read_iter = 0xffffffffa2723370.
[ 57.135569] blkdev_read_iter line 2039.
[ 57.135570] generic_file_buffered_read line 2055.
[ 438.531751] __vfs_read line 426, read = 0x0. read_iter = 0xffffffffa279aea0.
[ 438.531753] generic_file_buffered_read line 2055.
[ 438.531913] __vfs_read line 426, read = 0x0. read_iter = 0xffffffffa2723370.
[ 438.531914] blkdev_read_iter line 2039.
[ 438.531914] generic_file_buffered_read line 2055.
caozilong@caozilong-Vostro-3268:~/Workspace/linux-compile/linux-5.4.129$
证明Linux块设备的操作fops如下:
关于块设备读写的关键一步和最后一公里,是以下函数:
generic_make_request
一个O_DIRECT读写用例堆栈:
用普通方式带有page cache(非DIRECT模式)操作文件的调用堆栈