Wednesday, January 16, 2019

linux - Deciphering kpartx output




I hope I've posted this in the proper place, if I haven't then please advise me on where to move the post.



I've tried deciphering the kpartx output myself but now I'm sort of stuck and in need of guidance. I lack knowledge in many areas and I'm trying to improve, hence the deciphering. I'll post my problem and my findings so far and I'm hoping that someone out here could spare some of their time in guiding me in my troubleshooting/deciphering.



The problem



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



This number right here is my issue: 673171632. As far as I know, and also according to this answer https://serverfault.com/a/469734. This number should represent the number of blocks of this particular device.



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


But looking at the fdisk output, which I trust by experience, the number of blocks for this device is 336585816. To me, we have an inconsistency here. Since I trust fdisk by experience I was curious about how kpartx finds the number of blocks and then maybe look at fdisk and see how they differ from each other. So here is where the "deciphering" begun.



The actual question




I'm actually here for guidance, but in attempt to follow this forums guidelines and to help anyone else wondering the same thing:




How does kpartx determine it's output, in particular the number of
blocks?




My findings so far




My number one finding: I'm terrible at reading C code...



kpartx/kpartx.c:



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



To me it seems that this struct called slice(s) has an element (or whatever the term is), named size. That is the size of a partition in blocks. Which is what get's outputed to stdout. However, I don't understand how it get populated with actual numbers.



kpartx/kpartx.h



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

int minor;
};


This is what the struct looks like. Which seems to correpond to what kpartx outputs.



kpartx/kpart.c:



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

...
...
extern ptreader read_dos_pt;


These also seem intersting, I basing this on the name read_dos_pt, since the partition in questions is a dos partition and that ptreader seem to use the slice struct. Maybe to populate it?



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);


Here I notice the getblock function, which to me seems obvious for what I'm looking for. But looking at the getblock function in kpartx/kpartx.c I get lost and confused.




Any help I can get will be appreciated. Thank you for your time.


Answer



Not sure how relevant this is for serverfault, but I'll take it apart anyway.



Skip past getblock in read_dos_pt. Interesting part is on line 97. sp[i].size = sector_size_mul * le32_to_cpu(p.nr_sects);
sector_size_mul is the number of 512 byte sectors in one native sector for this disk (eg, 4k disks would have a sector_size_mul of 8). Most likely, this will be 1, especially if it's a file you're probing.



p.nr_sects is being populated directly from the on-disk dos partition table using memcpy. The osdev wiki has a nice tabular dos partition format description, so you can see the nr_sects structure field is a uint32_t starting at byte 12 of the partition entry (cf. dos.h offset of partition.nr_sects).




Thus what kpartx is putting in that field is "the number of 512 byte sectors in the partition, regardless of native sector size."



Going back to your fdisk output, it's pretty clearly in 1k blocks.



Divide your byte size by 1024 and you're going to get the 336585816 number you're seeing in fdisk, but divide by 512 and you'll get what kpartx shows you.


No comments:

Post a Comment

linux - How to SSH to ec2 instance in VPC private subnet via NAT server

I have created a VPC in aws with a public subnet and a private subnet. The private subnet does not have direct access to external network. S...