解读 kpartx 输出

解读 kpartx 输出

我希望我已经将此帖子发布到了正确的位置,如果没有,请告诉我将帖子移到哪里。

我曾尝试自己解读 kpartx 输出,但现在我有点卡住了,需要指导。我在很多方面都缺乏知识,我正在努力提高,因此才进行解读。我会发布我的问题和迄今为止的发现,我希望有人能抽出一些时间来指导我进行故障排除/解读。

问题

[root@hostname ~]# kpartx -l /dev/mapper/mpathcg 
mpathcg1 : 0 673171632 /dev/mapper/mpathcg 63

这个号码就是我的问题:673171632。据我所知,并且根据这个答案https://serverfault.com/a/469734. 这个数字应该代表这个特定设备的块数。

[root@hostname ~]# fdisk -l /dev/mapper/mpathcg

Disk /dev/mapper/mpathcg: 344.7 GB, 344671125504 bytes
255 heads, 63 sectors/track, 41903 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 32768 bytes / 32768 bytes
Disk identifier: 0xa5c9e23d

          Device Boot      Start         End      Blocks   Id  System
/dev/mapper/mpathcgp1               1       41903   336585816   8e  Linux LVM
Partition 1 does not start on physical sector boundary.

但是,根据我的经验,我信任 fdisk 的输出,该设备的块数为 336585816。对我来说,这里存在不一致。由于根据我的经验,我信任 fdisk,所以我很好奇 kpartx 如何找到块数,然后也许看看 fdisk 并看看它们彼此有何不同。所以这就是“解密”的开始。

实际问题

我来这里实际上是寻求指导,但是为了尝试遵循这个论坛的指导方针并帮助任何想知道同样事情的人:

kpartx 如何确定其输出,特别是块的数量?

我迄今为止的发现

我的第一发现是:我很不擅长阅读 C 代码......

kpartx/kpartx.c:

            printf("%s%s%d : 0 %" PRIu64 " %s %" PRIu64"\n",
                   mapname, delim, j+1,
                   slices[j].size, device,
                   slices[j].start);
        }

在我看来,这个名为切片的结构有一个元素(或任何术语),名为 size。这是分区的块大小。这就是输出到 stdout 的内容。但是,我不明白它是如何用实际数字填充的。

kpartx/kpartx.h

struct slice {
    uint64_t start;
    uint64_t size;
    int container;
    int major;
    int minor;
};

该结构如下所示。这似乎与 kpartx 输出的内容相对应。

kpartx/kpart.c:

typedef int (ptreader)(int fd, struct slice all, struct slice *sp, int ns);
...
...
...
extern ptreader read_dos_pt;

这些看起来也很有趣,我根据名称 read_dos_pt 得出这个结论,因为问题中的分区是 dos 分区,并且 ptreader 似乎使用了切片结构。也许是为了填充它?

kpartx/dos.c:

read_dos_pt(int fd, struct slice all, struct slice *sp, int ns) {
    struct partition p;
    unsigned long offset = all.start;
    int i, n=4;
    unsigned char *bp;
    uint64_t  sector_size_mul = get_sector_size(fd)/512;

    bp = (unsigned char *)getblock(fd, offset);

在这里我注意到 getblock 函数,对我来说,它显然就是我要找的东西。但是,查看 kpartx/kpartx.c 中的 getblock 函数时,我感到迷茫和困惑。

任何能得到的帮助我都会感激不尽。谢谢您抽出时间。

答案1

不确定这与服务器故障有多大关系,但我无论如何都会把它拆开。

跳过 read_dos_pt 中的 getblock。有趣的部分在第 97 行。sp[i].size = sector_size_mul * le32_to_cpu(p.nr_sects); sector_size_mul是此磁盘一个本机扇区中的 512 字节扇区数(例如,4k 磁盘的扇区数为sector_size_mul8)。最有可能的是,这个数字是 1,特别是如果它是您正在探测的文件。

p.nr_sects 是使用 memcpy 直接从磁盘上的 dos 分区表填充的。osdev wiki 有一个很好的表格dos分区格式说明,因此您可以看到 nr_sects 结构字段是一个 uint32_t,从分区条目的第 12 个字节开始(参见 dos.h 中 partion.nr_sects 的偏移量)。

因此,kpartx 在该字段中输入的是“分区中的 512 字节扇区的数量,无论原始扇区大小如何”。

回到您的 fdisk 输出,它显然是 1k 块。

将您的字节大小除以 1024,您将得到 fdisk 中看到的数字 336585816,但除以 512,您将得到 kpartx 显示的数字。

相关内容