DevOps/지식창고

LVM 메타데이터 (feat. dd)

WhiteDuck 2024. 2. 28. 22:32

본 포스팅은 LVM 2.2.02.187 을 기준으로 작성되었습니다.

디스크 덤프

다음과 같은 환경에서 /dev/sdd/dev/sde 의 덤프를 해보면 어떻게 나올까요?

  • PV 2 => VG => LV + Snapshot
# pvs
  PV         VG        Fmt  Attr PSize   PFree  
  /dev/sdd   thick     lvm2 a--  <50.00g  48.98g
  /dev/sde   thick     lvm2 a--  <50.00g <50.00g

# vgs
  VG        #PV #LV #SN Attr   VSize  VFree 
  thick       2   2   1 wz--n- 99.99g 98.98g

# lvs
  LV         VG        Attr       LSize  Pool Origin    Data%  Meta%  Move Log Cpy%Sync Convert
  thick_snap thick     swi-a-s--- 12.00m      thick_vol 0.00 
  thick_vol  thick     owi-a-s---  1.00g 
  • 덤프를 해볼까요?
# dd if=/dev/sdd of=/root/sdd_dump bs=1020k count=1
# dd if=/dev/sde of=/root/sde_dump bs=1020k count=1
  • 알아보기 쉽도록 hex 데이터로 바꿔봅시다.
# xxd sdd_dump > sdd_hex
# xxd sde_dump > sde_hex

당연하게도 LVM 라벨이 찍힌 디스크가 보입니다.

# cat sdd_hex | head -n 656

...
0000200: 4c41 4245 4c4f 4e45 0100 0000 0000 0000  LABELONE........
0000210: a982 7799 2000 0000 4c56 4d32 2030 3031  ..w. ...LVM2 001
0000220: 4a6f 6c4f 5177 7833 4466 5033 756a 6e75  JolOQwx3DfP3ujnu
0000230: 776e 6435 4342 4735 6230 6747 5975 3874  wnd5CBG5b0gGYu8t

/dev/sde 도 동일한지 살펴볼까요?

# cat sde_hex | head -n 656

...
0000200: 4c41 4245 4c4f 4e45 0100 0000 0000 0000  LABELONE........
0000210: 1d8e 939d 2000 0000 4c56 4d32 2030 3031  .... ...LVM2 001
0000220: 4647 5a33 4d45 6150 4c68 394e 784f 724f  FGZ3MEaPLh9NxOrO
0000230: 6e39 7a38 4172 6459 7071 4f33 6a35 6c52  n9z8ArdYpqO3j5lR

디스크에 쓰여진 데이터 해석

라벨이 찍혀있는 것은 동일하지만 그 뒤 정보는 약간 다른 것을 볼 수 있습니다. 위의 정보는 도대체 뭘까요?

$ cat lib/label/label.h

35 /* On disk - 32 bytes */
36 struct label_header {
37 >---int8_t id[8];>-->---/* LABELONE */
38 >---uint64_t sector_xl;>/* Sector number of this label */
39 >---uint32_t crc_xl;>---/* From next field to end of sector */
40 >---uint32_t offset_xl;>/* Offset from start of struct to contents */
41 >---int8_t type[8];>>---/* LVM2 001 */
42 } __attribute__ ((packed));

LVM 소스에서 확인해보니 라벨, 섹터정보, crc 정보, offset 정보, LVM 타입 등이 보이네요.

아 그러면은 LVM 에서 사용하는 실제 섹터가 어디에 위치에 있는지 확인도 하고 디스크가 LVM 에서 쓰이는지 확인하려고 라벨을 달아둔 것 같네요~

그 다음 내용은 뭘까요?

# cat sde_hex | head -n 656

...
0000220: 4647 5a33 4d45 6150 4c68 394e 784f 724f  FGZ3MEaPLh9NxOrO
0000230: 6e39 7a38 4172 6459 7071 4f33 6a35 6c52  n9z8ArdYpqO3j5lR
0000240: 0000 0080 0c00 0000 0000 1000 0000 0000  ................ 
0000250: 0000 0000 0000 0000 0000 0000 0000 0000  ................
0000260: 0000 0000 0000 0000 0010 0000 0000 0000  ................
0000270: 00f0 0f00 0000 0000 0000 0000 0000 0000  ................
0000280: 0000 0000 0000 0000 0200 0000 0100 0000  ................
0000290: 0000 0000 0000 0000 0000 0000 0000 0000  ................



$ cat lib/format_text/layout.h

40 /* Fields with the suffix _xl should be xlate'd wherever they appear */
41 /* On disk */
42 struct pv_header {
43 >---int8_t pv_uuid[ID_LEN];
44
45 >---/* This size can be overridden if PV belongs to a VG */
46 >---uint64_t device_size_xl;>---/* Bytes */
47
48 >---/* NULL-terminated list of data areas followed by */
49 >---/* NULL-terminated list of metadata area headers */
50 >---struct disk_locn disk_areas_xl[0];>-/* Two lists */
51 } __attribute__ ((packed));
52
53 /*
54 * Ignore this raw location. This allows us to

pvcreate 시에 pvuuid 의 정보에 대해서 저장을 해뒀나 보네요. pv 의 uuid 와 디바이스의 정보를 포함하고 있습니다.

disk_areas_xl 에는 각각 데이터 영역 정보와 메타데이터 영역 정보를 포함하고 있습니다. 영역 정보는 리스트로 들어갈 수 있는데, 리스트가 끝났다면 zero 값으로 offsetsize 를 채워넣습니다.

$ cat lib/format_text/format-text.h

67 /* On disk */
68 struct disk_locn {
69 >---uint64_t offset;>---/* Offset in bytes to start sector */
70 >---uint64_t size;>->---/* Bytes */
71 } __attribute__ ((packed));

아래에서 보면 0000 1000 0000 0000 값이 데이터 영역의 offset, 0000 0000 0000 0000 이 데이터 영역의 size 임을 확인할 수 있습니다.

offset, size 등은 bswap 을 사용하여 저장하고 읽습니다. 위의 0000 1000 0000 0000는 그러므로 x100000 값으로 읽을 수 있습니다.

0000240: 0000 0080 0c00 0000 0000 1000 0000 0000  ................ 
0000250: 0000 0000 0000 0000 0000 0000 0000 0000  ................
0000260: 0000 0000 0000 0000 0010 0000 0000 0000  ................
0000270: 00f0 0f00 0000 0000 0000 0000 0000 0000  ................
0000280: 0000 0000 0000 0000 0200 0000 0100 0000  ................

데이터 영역의 위치로 가면 아직 아무것도 작성을 하지 않아서 그런지 아무것도 없습니다.

0100000: 0000 0000 0000 0000 0000 0000 0000 0000  ................
0100010: 0000 0000 0000 0000 0000 0000 0000 0000  ................
0100020: 0000 0000 0000 0000 0000 0000 0000 0000  ................
0100030: 0000 0000 0000 0000 0000 0000 0000 0000  ................
0100040: 0000 0000 0000 0000 0000 0000 0000 0000  ................
0100050: 0000 0000 0000 0000 0000 0000 0000 0000  ................
0100060: 0000 0000 0000 0000 0000 0000 0000 0000  ................
0100070: 0000 0000 0000 0000 0000 0000 0000 0000  ................
0100080: 0000 0000 0000 0000 0000 0000 0000 0000  ................

하지만 메타데이터 영역의 위치(x10 00) 으로 가면 메타데이터의 헤더가 있는 것을 확인할 수 있죠.

0001000: 2af4 634e 204c 564d 3220 785b 3541 2572  *.cN LVM2 x[5A%r
0001010: 304e 2a3e 0100 0000 0010 0000 0000 0000  0N*>............
0001020: 00f0 0f00 0000 0000 00a0 0100 0000 0000  ................
0001030: 0007 0000 0000 0000 a181 917c 0000 0000  ...........|....
0001040: 0000 0000 0000 0000 0000 0000 0000 0000  ................
0001050: 0000 0000 0000 0000 0000 0000 0000 0000  ................
0001060: 0000 0000 0000 0000 0000 0000 0000 0000  ................
0001070: 0000 0000 0000 0000 0000 0000 0000 0000  ................
0001080: 0000 0000 0000 0000 0000 0000 0000 0000  ................

메타데이터 헤더는 어떻게 구성되어 있을까요?

$ cat lib/format_text/layout.h

 71 /* On disk */
 72 /* Structure size limited to one sector */
 73 struct mda_header {
 74 >---uint32_t checksum_xl;>--/* Checksum of rest of mda_header */
 75 >---int8_t magic[16];>--/* To aid scans for metadata */
 76 >---uint32_t version;
 77 >---uint64_t start;>>---/* Absolute start byte of mda_header */
 78 >---uint64_t size;>->---/* Size of metadata area */
 79 
 80 >---struct raw_locn raw_locns[0];>--/* NULL-terminated list */
 81 } __attribute__ ((packed));

 60 /* On disk */
 61 struct raw_locn {
 62 >---uint64_t offset;>---/* Offset in bytes to start sector */
 63 >---uint64_t size;>->---/* Bytes */
 64 >---uint32_t checksum;
 65 >---uint32_t flags;
 66 } __attribute__ ((packed));

메타데이터 헤더는 헤더 정보의 유효성을 검증하고 메타데이터의 위치를 가리키고 있습니다.
실제로 메타데이터는 mda_header->start + raw_locns->offset 에서 확인이 가능합니다.
한번 가 볼까요?

  • 이제 주소를 계산하는 것도 어렵지 않습니다!
  • x1000 + x1a000 = x1b000
001b000: 7468 6963 6b20 7b0a 6964 203d 2022 3266  thick {.id = "2f
001b010: 7559 4431 2d48 5856 792d 315a 3275 2d76  uYD1-HXVy-1Z2u-v
001b020: 797a 332d 7765 4530 2d6c 6553 4a2d 716e  yz3-weE0-leSJ-qn
001b030: 6d79 784f 220a 7365 716e 6f20 3d20 3333  myxO".seqno = 33
001b040: 0a66 6f72 6d61 7420 3d20 226c 766d 3222  .format = "lvm2"
001b050: 0a73 7461 7475 7320 3d20 5b22 5245 5349  .status = ["RESI
001b060: 5a45 4142 4c45 222c 2022 5245 4144 222c  ZEABLE", "READ",
001b070: 2022 5752 4954 4522 5d0a 666c 6167 7320   "WRITE"].flags.
001b080: 3d20 5b5d 0a65 7874 656e 745f 7369 7a65  = [].extent_size

참고

반응형

'DevOps > 지식창고' 카테고리의 다른 글

Devel  (0) 2024.04.01
Samba VFS  (0) 2024.03.30
LVM Thin  (0) 2024.02.11
NFS  (0) 2023.12.16
Paxos 기능 개발기 - 개념 정리(2)  (0) 2023.12.15
Paxos 기능 개발기 - 개념정리(1)  (1) 2023.12.11
VDI(Virtual Desktop Infrastructur  (1) 2023.12.07
SAN  (0) 2023.12.02