我正在寻找一个明确的规范,该规范描述了ioctl 0x1268(BLKSSZGET)的预期参数和行为。

在许多地方都声明了这个数字(没有一个地方包含确定的引用源),例如linux/fs.h,但是我找不到关于它的任何规范。

当然,过去某个时候有人认为0x1268将获得设备的物理扇区大小,并在某处进行了记录。这些信息从何而来?在哪里可以找到?

编辑:我不是在问BLKSSZGET通常做什么,也不是在问它定义在哪个 header 中。我正在寻找一个确定的,标准化的源,该源说明应采用的参数类型以及其对任何驱动程序的行为实现它。

具体来说,我要问是因为在util-linux 2.23(和2.24)中blkdiscard中似乎有一个错误,其中将扇区大小查询到uint64_t,但是高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/

最佳答案

答案是“在哪里指定?”确实是内核的来源。

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

作为回应,Theodore Ts'o 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.

然后,他继续在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具有int,但是有关文档的一般问题仍然存在。然后,我跟进了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.

我还询问了在公共(public)内核API his response is there中通常使用“int”的问题,尽管此处不合主题。

答案:因此,您已经拥有了,最后的答案是:ioctl接口(interface)由内核源本身指定;没有内核遵循的文档。有文档描述了各种ioctl的内核实现,但是如果存在不匹配,则说明文档中存在错误,而不是内核中的错误。

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

关于linux - ioctl参数(例如0x1268/BLKSSZGET)在哪里实际指定?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/19747663/

10-13 05:23