我有一个用户空间应用程序,可以生成大的SCSI写入(详情如下)。但是,当我查看到达SCSI目标的SCSI命令(即由FC连接的存储器)时,有些东西会将这些写入分成512K块。
应用程序基本上直接将1M大小的直接写入设备:
fd = open("/dev/sdab", ..|O_DIRECT);
write(fd, ..., 1024 * 1024);
此代码导致发送两个SCSI WRITE,每个512K。
但是,如果我发出直接SCSI命令,没有阻止层,则不会分割写入。 我从命令行发出以下命令:
sg_dd bs=1M count=1 blk_sgio=1 if=/dev/urandom of=/dev/sdab oflag=direct
我可以看到一个1M大小的SCSI WRITE。
问题是,什么是分割写入,更重要的是,它是可配置的? Linux块层似乎是有罪的(因为SG_IO没有通过它)和512K似乎太任意一个数字不是某种可配置参数。
答案 0 :(得分:1)
责任确实在阻挡层上,SCSI层本身很少考虑到大小。您应该检查底层是否确实能够传递您的请求,特别是关于直接io,因为它可能被拆分成许多小页面并且需要一个比硬件支持的更长的分散 - 收集列表或者甚至只是司机(libata是/有点受限)。
你应该查看并调整/ sys / class / block / $ DEV / queue那里有各种各样的文件,最有可能匹配你需要的是max_sectors_kb但是你可以尝试一下,看看哪些对你有用。您可能还需要调整分区变量。
答案 1 :(得分:0)
查看以下文件应该告诉您逻辑块大小是否不同,在您的情况下可能是512。我不确定你是否可以写这些文件来改变这些值。 (逻辑块大小)
/sys/block/<disk>/queue/physical_block_size
/sys/block/<disk>/queue/logical_block_size
答案 2 :(得分:0)
块驱动程序的每个请求属性有一个最大扇区。我必须检查如何修改它。您曾经能够通过blockdev --getmaxsect获取此值,但我没有在我的机器的blockdev上看到--getmaxsect选项。
答案 3 :(得分:0)
尝试ioctl(fd,BLKSECTSET和&amp; blocks)
答案 4 :(得分:0)
如内核块层维护者Jens Axboe对"Why is the size of my IO requests being limited, to about 512K" Unix&Linux Stack Exchange问题的回答和“ When 2MB turns into 512KB”文档的“设备限制”部分所述,可能是因为您的设备和内核有大小限制(在/sys/block/<disk>/queue/
中可见):
max_hw_sectors_kb
硬件可以接受的单个I / O的最大大小max_sectors_kb
块层将发送的最大大小max_segment_size
和max_segments
对分散收集(SG)I / O的DMA引擎限制(每个段的最大大小和单个I / O的最大段数)当I / O来自的缓冲区不连续时,段限制非常重要,在最坏的情况下,每个段都可以和页面一样小(在x86平台上为4096字节)。这意味着一个I / O的SG I / O可以限制为4096 * {max_segments
。
问题是,什么在拆分写入内容
您猜到了Linux块层。
,更重要的是,它是否可配置?
您可以摆弄max_sectors_kb
,但其余部分是固定的,并且受设备/驱动程序限制的影响(因此,我猜测可能不是,但重启后您可能会直接看到更大的I / O)减少内存碎片)。
512K似乎太随意了,不能成为某种可配置的参数
该值可能与片段SG缓冲区有关。假设您使用的是x86平台,并且max_segments
为128
,因此:
4096 * 128 / 1024 = 512
这就是512K可能来自的地方。
奖金chat不休:根据https://twitter.com/axboe/status/1207509190907846657的说法,如果您的设备使用IOMMU而不是DMA引擎,则您不应受到网段限制...