ioctl参数(例如0x1268/BLKSSZGET)在哪里实际指定?

问题描述:

我正在寻找描述ioctl 0x1268(BLKSSZGET)的预期参数和行为的明确规范。ioctl参数(例如0x1268/BLKSSZGET)在哪里实际指定?

这个数字在许多地方被声明(其中没有一个包含明确的参考源),例如linux/fs.h,但是我没有找到它的规范。

当然,有人在过去的某个时间点决定0x1268会获得设备的物理扇区大小并在某处记录。这些信息来自哪里,我可以在哪里找到它?

编辑:我不是问一般BLKSSZGET做什么,也不是问我在什么头被定义。我正在寻找一个明确的,标准化的来源,说明它应该采取什么样的参数类型和它的行为应该是什么对于实现它的任何驱动程序。

具体而言,我要求,因为有似乎是一个错误在blkdiscard在所述扇区大小被查询到uint64_t util的Linux的2.23(2.24),但高32比特是不变因为BLKSSZGET 出现以期望32位整数,并且这会导致扇区大小不正确,对齐计算不正确以及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/

+0

谢谢,但我已经知道BLKSSZGET的功能。我正在寻找一个明确的行为规范。特别是,它是否需要一个指向32或64位整数的指针作为参数,更重要的是,*你怎么知道*? –

+0

够公平的,我知道0,认为这可能有帮助;将继续挖掘。 – slm

+0

鉴于少数人可能知道这个,你可以详细说明你的Q有点添加上下文吗? – slm

“这是指定的地方?”的答案似乎是内核源。

我问的问题内核邮件列表在这里:https://lkml.org/lkml/2013/11/1/620

对此,曹子德wrote(注:他错误地识别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. 

然后,他接着提出patch¹在UTIL-linux下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),回答了这个问题。他wrote

> 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. 

我也问了一下,一般使用“INT”的公共内核API,his response is there尽管这是题外话这里。

答案:所以,你有它,最后的答案是:ioctl接口由内核源自己指定;没有内核遵守的文件。有文档来描述内核各种ioctl的实现,但是如果有不匹配的地方,这是文档中的错误,而不是内核中的错误。

¹考虑到以上所有内容,我想指出Theodore Ts'o提交的补丁与我的相比,重要的区别是使用“int”而不是“uint32_t” - BLKSSZGET ,根据内核源代码,确实期望在平台上的大小为“int”,而不是强制的32位值。