我正在寻找描述ioctl 0x1268(BLKSSZGET)的预期参数和行为的明确规范。
这个数字在很多地方都被声明(其中没有一个包含明确的参考源),比如linux/fs.h
,但是我没有find它的规范。
当然,在过去的某个时刻,有人决定0x1268会得到设备的物理扇区大小,并在某个地方logging下来。 这些信息来自哪里,我可以在哪里find它?
编辑:我不是问BLKSSZGET一般做什么,也不是问我在什么头被定义。我正在寻找一个明确的,标准化的来源,说明什么样的参数types应该采取什么样的行为应该是任何驱动程序实现它。
具体来说,我问的是,在util-linux 2.23(和2.24)的blkdiscard
里面有一个错误,其中的扇区大小被查询到uint64_t
,但是高32位没有受到影响,因为BLKSSZGET 似乎期望一个32-这会导致不正确的扇区大小,不正确的alignment计算以及应该成功的blkdiscard
失败。 所以在提交补丁之前,我需要绝对确定地确定问题是blkdiscard
应该使用32位整数,还是我的内核中的驱动程序应该使用64位整数。
编辑2:由于我们在这个话题上,所提议的补丁假设blkdiscard
是不正确的是:
--- sys-utils/blkdiscard.c-2.23 2013-11-01 18:28:19.270004947 -0400 +++ sys-utils/blkdiscard.c 2013-11-01 18:29:07.334002382 -0400 @@ -71,7 +71,8 @@ { char *path; int c, fd, verbose = 0, secure = 0; - uint64_t end, blksize, secsize, range[2]; + uint64_t end, blksize, range[2]; + uint32_t secsize; struct stat sb; static const struct option longopts[] = { @@ -146,8 +147,8 @@ err(EXIT_FAILURE, _("%s: BLKSSZGET ioctl failed"), path); /* align range to the sector size */ - range[0] = (range[0] + secsize - 1) & ~(secsize - 1); - range[1] &= ~(secsize - 1); + range[0] = (range[0] + (uint64_t)secsize - 1) & ~((uint64_t)secsize - 1); + range[1] &= ~((uint64_t)secsize - 1); /* is the range end behind the end of the device ?*/ end = range[0] + range[1];
应用于例如https://www.kernel.org/pub/linux/utils/util-linux/v2.23/ 。
“这是指定的地方?”的答案 似乎是内核的来源。
我在这里问了关于内核邮件列表的问题: https : //lkml.org/lkml/2013/11/1/620
作为回应,Theodore Ts'o 写道 (注意:他错误地在他的列表中标识了sys-utils / blkdiscard.c,但这是无关紧要的):
BLKSSZGET returns an int. If you look at the sources of util-linux v2.23, you'll see it passes an int to BLKSSZGET in sys-utils/blkdiscard.c lib/blkdev.c E2fsprogs also expects BLKSSZGET to return an int, and if you look at the kernel sources, it very clearly returns an int. The one place it doesn't is in sys-utils/blkdiscard.c, where as you have noted, it is passing in a uint64 to BLKSSZGET. This looks like it's a bug in sys-util/blkdiscard.c.
然后,他在util-linux上提交了patch1到blkdiscard:
--- a/sys-utils/blkdiscard.c +++ b/sys-utils/blkdiscard.c @@ -70,8 +70,8 @@ static void __attribute__((__noreturn__)) usage(FILE *out) int main(int argc, char **argv) { char *path; - int c, fd, verbose = 0, secure = 0; - uint64_t end, blksize, secsize, range[2]; + int c, fd, verbose = 0, secure = 0, secsize; + uint64_t end, blksize, range[2]; struct stat sb; static const struct option longopts[] = {
我一直犹豫在我的邮件列表文章和这个SO问题的原始版本中提到blkdiscard工具,具体是因为这个原因:我知道我的内核源代码中有什么,已经很容易修改blkdiscard来同意源代码,这最终导致了“真实存在的地方”的真正问题。
所以,就具体情况而言,比我更为官方的人也表示BLKSSZGET ioctl是一个整数,但关于文档的一般问题依然存在。 然后我跟进了https://lkml.org/lkml/2013/11/3/125,并收到了另一个来自Theodore Ts'o( wiki for credibility)的答复,回答了这个问题。 他写道 :
> There was a bigger question hidden behind the context there that I'm > still wondering about: Are these ioctl interfaces specified and > documented somewhere? From what I've seen, and from your response, the > implication is that the kernel source *is* the specification, and not > document exists that the kernel is expected to comply with; is this > the case? The kernel source is the specification. Some of these ioctl are documented as part of the linux man pages, for which the project home page is here: https://www.kernel.org/doc/man-pages/ However, these document existing practice; if there is a discrepancy between what is in the kernel has implemented and the Linux man pages, it is the Linux man pages which are buggy and which will be changed. That is man pages are descriptive, not perscriptive.
我还询问了关于公共内核API的“int”的用法, 他的回答是在那里,尽管这里是关键的话题。
答:所以,你有它,最后的答案是:ioctl接口是由内核源自己指定的; 没有内核遵守的文件。 有文档来描述内核的各种ioctl的实现,但是如果不匹配的话,这是文档中的错误,而不是内核中的错误。
¹综上所述,我想指出,Theodore Ts'o提交的补丁与我的相比有一个重要的区别,就是使用“int”而不是“uint32_t” – BLKSSZGET,按内核源,确实希望有一个参数,即平台上的“int”大小,而不是强制的32位值。