Làm cách nào tôi có thể tìm ra phạm vi LBA của một tệp bằng cách sử dụng inode của nó?


9

Trong khi trả lời câu hỏi U & L này có tiêu đề: Tôi sử dụng lệnh nào để xem khối bắt đầu và kết thúc của một tệp trong hệ thống tệp? , Tôi đã cố gắng tìm hiểu xem có thể xác định LBA của tệp bằng cách sử dụng inode không.

Câu trả lời của tôi xác định rằng tôi có thể sử dụng hdparmnhư một phương pháp để tìm LBA:

$ sudo hdparm --fibmap afile 

afile:
 filesystem blocksize 4096, begins at LBA 0; assuming 512 byte sectors.
 byte_offset  begin_LBA    end_LBA    sectors
           0  282439184  282439191          8

Nhưng tôi đã tò mò nếu có một số phương pháp sử dụng inode của tập tin để lấy LBA; mà không sử dụng hdparm.

Tôi nghĩ rằng có thể có một phương pháp thay thế trốn trong các công cụ filefrag, stat, debugfs, và tune2fsnhưng trêu chọc nó ra được eluding tôi.

Bất cứ ai cũng có thể nghĩ đến các lựa chọn thay thế?


Đây là một số nghiên cứu của tôi cho đến nay có thể hữu ích cho những người đủ can đảm để cố gắng trả lời điều này.

filefrag

Tôi nghi ngờ bạn có thể sử dụng công cụ filefragđể thực hiện, cụ thể là sử dụng kết quả từ công -etắc của nó , có lẽ bằng cách thực hiện một số tính toán để đạt được điều đó mà tôi không quen thuộc.

đầu ra mẫu

$ filefrag -e afile
Filesystem type is: ef53
File size of afile is 20 (1 block of 4096 bytes)
 ext:     logical_offset:        physical_offset: length:   expected: flags:
   0:        0..       0:   35304898..  35304898:      1:             eof
afile: 1 extent found

inodes

Một phương pháp tiềm năng khác mà tôi nghi ngờ có thể có tiềm năng là sử dụng thông tin inode của tệp, trực tiếp hoặc thông qua một số phép toán phức tạp được ghi lại kém trên các interwebs.

Thí dụ

Đầu tiên chúng ta tìm ra inode của tập tin. Chúng ta có thể làm điều này bằng cách sử dụng statlệnh hoặc ls -i.

chỉ số

$ stat afile 
  File: ‘afile’
  Size: 20          Blocks: 8          IO Block: 4096   regular file
Device: fd02h/64770d    Inode: 6560281     Links: 1
Access: (0664/-rw-rw-r--)  Uid: ( 1000/    saml)   Gid: ( 1000/    saml)
Context: unconfined_u:object_r:user_home_t:s0
Access: 2013-12-27 18:40:12.788333778 -0500
Modify: 2013-12-27 18:40:23.103333073 -0500
Change: 2013-12-27 18:44:03.697317989 -0500
 Birth: -

ls -i

$ ls -i 
6560281 afile

Với thông tin inode trong tay, giờ đây chúng ta có thể mở hệ thống tệp mà tệp này cư trú bằng cách sử dụng công cụ , debugfs.

GHI CHÚ: Để xác định hệ thống tệp, một tệp nằm trong đó bạn có thể sử dụng lệnh df <filename>.

Bây giờ nếu chúng ta chạy debugfsvà chạy lệnh, stat <inode #>chúng ta có thể nhận được một danh sách các phạm vi có chứa dữ liệu của tệp này.

$ sudo debugfs -R "stat <6560281>" /dev/mapper/fedora_greeneggs-home
debugfs 1.42.7 (21-Jan-2013)
Inode: 6560281   Type: regular    Mode:  0664   Flags: 0x80000
Generation: 1999478298    Version: 0x00000000:00000001
User:  1000   Group:  1000   Size: 20
File ACL: 0    Directory ACL: 0
Links: 1   Blockcount: 8
Fragment:  Address: 0    Number: 0    Size: 0
 ctime: 0x52be10c3:a640e994 -- Fri Dec 27 18:44:03 2013
 atime: 0x52be0fdc:bbf41348 -- Fri Dec 27 18:40:12 2013
 mtime: 0x52be0fe7:18a2f344 -- Fri Dec 27 18:40:23 2013
crtime: 0x52be0dd8:64394b00 -- Fri Dec 27 18:31:36 2013
Size of extra inode fields: 28
Extended attributes stored in inode body: 
  selinux = "unconfined_u:object_r:user_home_t:s0\000" (37)
EXTENTS:
(0):35304898

Bây giờ chúng tôi có các thông tin về phạm vi ở trên và đây là nơi tôi bị lạc và không biết cách tiến hành.

Người giới thiệu

Câu trả lời:


5

filefragdebugfsbáo cáo bù được thể hiện bằng số khối hệ thống tập tin.

Để có được độ lệch theo số đơn vị 512 byte, bạn cần nhân với kích thước của khối theo đơn vị 512 byte. Trên ext4 FS, kích thước khối thường là 4k, vì vậy bạn cần nhân với 8.

Với filefrag, bạn cũng có thể sử dụng một -b 512tùy chọn để lấy phần bù theo đơn vị 512 byte.

Bạn có thể lấy kích thước khối bằng statslệnh in debugfshoặc với GNU stat:

stat -fc%s /mount/point

(hoặc bất kỳ tập tin trong hệ thống tập tin đó).

Lưu ý rằng đó hdparmlà một tiện ích đĩa cứng, nó sẽ cố gắng bù đắp trong đĩa trái ngược với thiết bị khối mà hệ thống tệp được gắn vào (giả sử rằng thiết bị khối nào đó nằm trên đĩa bằng cách nào đó). Nó chỉ hoạt động theo cách đó đối với các phân vùng (bằng cách thêm nội dung /sys/class/block/the-block-device/startvào phần bù thực tế) và các thiết bị md RAID 1, chứ không phải các loại thiết bị chặn đĩa có thể khác như thiết bị ánh xạ thiết bị, các cấp RAID khác, thiết bị sợ, vòng lặp, nbd. .. Cũng lưu ý rằng các phiên bản cũ hơn hdparmdựa trên ioctl FIBMAP bị giới hạn trong thiết bị khối nào có thể được sử dụng, trong khi các phiên bản mới hơn sử dụng FIEMAP như thế nào filefrag.

Vì vậy, ví dụ, nếu bạn có một ext2hệ thống tập tin trên /dev/sda1.

# hdparm --fibmap /file/in/there
/file/in/there:
 filesystem blocksize 1024, begins at LBA 2048; assuming 512 byte sectors.
 byte_offset  begin_LBA    end_LBA    sectors
           0     109766     109767          2

Bạn có thể nhận được hai lĩnh vực đó (nhưng lưu ý rằng tệp có thể chỉ sử dụng một phần của nó):

dd skip=109766 count=2 if=/dev/sda # not /dev/sda1

Trong khi với filefraghoặc gỡ lỗi.

# filefrag -v /file/in/there
Filesystem type is: ef53
Filesystem cylinder groups is approximately 12
File size of /file/in/there is 87 (1 block, blocksize 1024)
 ext logical physical expected length flags
   0       0    53859               1 merged,eof

Bạn nhận được nó từ thiết bị khối thực tế:

dd bs=1024 skip=53859 count=1 if=/dev/sda1

Vì vậy, nếu tôi hiểu bạn một cách chính xác, nếu filefrag -b512 -v ..nói "vật lý_offset: 211787168 .. 211795719" thì những điều này sẽ tương đương với các LBA? Điều này dường như jive với cùng một tập tin với hdparm --fibmap, 211787168..211795719. Nếu tôi thả -b512 -vvà sử dụng def. 1024, và cố gắng để nhiều. trước 8, 26473396⋅8..26474464⋅8, tôi nhận được 211787168..211795712, gần nhưng hơi tắt. Tôi nghĩ giá trị thứ 2 phải là (26474465⋅8) -1 = 211795719, không chắc tại sao.
slm

Bạn có suy nghĩ gì về cách lấy các khối trong 512 đơn vị từ debugfs không?
slm

Cuối cùng tôi đã thực hiện các tính toán để chuyển đổi từ phạm vi sang LBA bằng cách sử dụng cùng một phép toán ở trên.
slm

2

Hóa ra để chuyển đổi từ phạm vi sang LBA thực sự khá đơn giản một khi bạn hiểu các con số đến từ đâu. Câu trả lời của @StephaneChazelas là rất quan trọng để đạt được sự hiểu biết này.

Đầu ra gỡ lỗi gốc

Sử dụng ví dụ sau đây đã được đề cập trong câu hỏi.

$ sudo debugfs -R "stat <6560281>" /dev/mapper/fedora_greeneggs-home
debugfs 1.42.7 (21-Jan-2013)
Inode: 6560281   Type: regular    Mode:  0664   Flags: 0x80000
Generation: 1999478298    Version: 0x00000000:00000001
User:  1000   Group:  1000   Size: 20
File ACL: 0    Directory ACL: 0
Links: 1   Blockcount: 8
Fragment:  Address: 0    Number: 0    Size: 0
 ctime: 0x52be10c3:a640e994 -- Fri Dec 27 18:44:03 2013
 atime: 0x52be0fdc:bbf41348 -- Fri Dec 27 18:40:12 2013
 mtime: 0x52be0fe7:18a2f344 -- Fri Dec 27 18:40:23 2013
crtime: 0x52be0dd8:64394b00 -- Fri Dec 27 18:31:36 2013
Size of extra inode fields: 28
Extended attributes stored in inode body: 
  selinux = "unconfined_u:object_r:user_home_t:s0\000" (37)
EXTENTS:
(0):35304898

Với thông tin về phạm vi, chúng tôi có thể thực hiện các tính toán sau. Nhưng chúng ta cần thêm một phần thông tin. Kích thước khối của hệ thống tập tin cơ bản. Bạn có thể sử dụng lệnh này để có được nó.

Kích thước khối

$ sudo tune2fs -l /dev/mapper/fedora_greeneggs-home | grep "Block size"
Block size:               4096

Chuyển đổi từ mức độ sang LBA

Vì vậy, biến đổi chính để nhận ra ở đây là các LBA có đơn vị 512 byte và debugfslệnh trên đã báo cáo số lượng phạm vi, đang báo cáo rằng trong các khối 4096 byte.

Vì vậy, 4096/512 = 8. Vì vậy, chúng ta cần nhân các phạm vi với 8 để chuyển đổi chúng thành các giá trị LBA.

Vì vậy, toán học sau đây sẽ cho chúng ta LBA khởi đầu:

$ calc -d
; 35304898 * 8
    282439184
; 

Vậy LBA kết thúc của chúng ta là gì? Để có được điều đó, chúng ta cần nhận ra rằng inode của chúng ta nằm gọn trong một khối duy nhất để mức độ kết thúc của nó giống với phạm vi bắt đầu của nó. Để tính LBA kết thúc, chúng ta có thể sử dụng phương trình này.

ending LBA = ( (extent + 1) * 8 ) - 1

Vì vậy, thực hiện tính toán này:

$ calc -d
; ( (35304898 + 1) * 8 ) - 1
    282439191

Khẳng định kết quả

Nhìn vào đầu hdparmra ban đầu:

 byte_offset  begin_LBA    end_LBA    sectors
           0  282439184  282439191          8

Chúng tôi thấy rằng mọi thứ phù hợp.

Một vi dụ khac

Chỉ để đảm bảo rằng chúng tôi đúng đây là một tệp lớn hơn làm ví dụ thứ 2.

$ ls -i util-linux-2.19.tar.bz2 
6559005 util-linux-2.19.tar.bz2

Đây là phạm vi của inode.

$ sudo debugfs -R "stat <6559005>" /dev/mapper/fedora_greeneggs-home
...
EXTENTS:
(0-1068):26473396-26474464

Bây giờ chúng tôi thực hiện chuyển đổi từ phạm vi sang LBA.

$ calc -d
; 26473396*8
    211787168
; (26474464+1)*8 - 1
    211795719

Và chúng tôi xác nhận.

$ sudo hdparm --fibmap util-linux-2.19.tar.bz2 
...
 byte_offset  begin_LBA    end_LBA    sectors
           0  211787168  211795719       8552

Và chúng tôi lại hợp nhau.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.