10

I am using dm-cache successfully for quite a while now. Now I would like to know which files are being currently in the cache. I understand that dm-cache works with blocks, not files, but since there is a filesystem above it should be possible in theory to translate this to (parts of) files being cached.

Of course I care about a practical solution: How can I list what is currently in dm-cache?

1 Answer 1

1

According to kernel documentation, dm-cache has metadata, which is one family with thin-provisioning metadata:

The target reuses the metadata library used in the thin-provisioning library.

Thus you can use the thin-provisioning-tools package, which provides cache_dump.

The use of this tool is not very straightforward, however. The README suggests you have to snapshot the device first, but even so, I couldn't get it to work at all.

# cache_dump /dev/mapper/foo-bar_cmeta
syscall 'open' failed: Device or resource busy
Note: you cannot run this tool with these options on live metadata.

So I ended up doing something weird instead:

# cp /dev/mapper/foo-bar_cmeta /dev/shm
# losetup --find --show /dev/shm/foo-bar_cmeta
/dev/loop1
# cache_dump /dev/loop1

Result:

<superblock uuid="" block_size="128" nr_cache_blocks="16384" policy="smq" hint_width="4">
  <mappings>
    <mapping cache_block="0" origin_block="163832" dirty="false"/>
    <mapping cache_block="1" origin_block="163833" dirty="false"/>
    <mapping cache_block="2" origin_block="163834" dirty="false"/>
    ...
    <mapping cache_block="5295" origin_block="16568" dirty="false"/>
    <mapping cache_block="5296" origin_block="16569" dirty="false"/>
    <mapping cache_block="5297" origin_block="16570" dirty="false"/>

So, what do we have here. A block size of "128" (sectors), and the first block ("0") in the cache device is supposed to be identical with block "163832" of the origin device. Let's check if it makes any sense at all.

For <mapping cache_block="0" origin_block="163832" dirty="false"/>:

# hexdump -C --skip $((512*128*0)) -n 32 /dev/mapper/foo-bar_cdata 
00000000  61 51 a3 09 88 ad 72 f8  6a 90 7f 93 fd 64 c0 c3  |aQ....r.j....d..|
00000010  e4 01 c5 cf e1 ba 37 53  d0 d8 06 cf 3a da d8 2d  |......7S....:..-|
00000020
# hexdump -C --skip $((512*128*163832)) -n 32 /dev/mapper/foo-bar_corig 
27ff80000  61 51 a3 09 88 ad 72 f8  6a 90 7f 93 fd 64 c0 c3  |aQ....r.j....d..|
27ff80010  e4 01 c5 cf e1 ba 37 53  d0 d8 06 cf 3a da d8 2d  |......7S....:..-|
27ff80020

For <mapping cache_block="5297" origin_block="16570" dirty="false"/>:

# hexdump -C --skip $((512*128*5297)) -n 32 /dev/mapper/foo-bar_cdata 
14b10000  68 72 65 61 64 5d 3a 20  56 2f 6e 73 48 74 74 70  |hread]: V/nsHttp|
14b10010  20 30 30 30 30 33 44 31  30 3a 20 30 33 20 44 37  | 00003D10: 03 D7|
14b10020
# hexdump -C --skip $((512*128*16570)) -n 32 /dev/mapper/foo-bar_corig 
40ba0000  68 72 65 61 64 5d 3a 20  56 2f 6e 73 48 74 74 70  |hread]: V/nsHttp|
40ba0010  20 30 30 30 30 33 44 31  30 3a 20 30 33 20 44 37  | 00003D10: 03 D7|
40ba0020

Looks good to me. Everything else is the same old "figure out which file is where". It can be done with filefrag, hdparm --fibmap or filesystem-specific tools like debugfs icheck. Same old unfortunately does not mean simple...

This is the very stupid, very manual approach:

# echo $((512*128*16570/4096))
265120
# filefrag -v -e *
[...]
File size of firefox-network.log-main.2270 is 605582660 (147848 blocks of 4096 bytes)
 ext:     logical_offset:        physical_offset: length:   expected: flags:
   0:        0..  147847:     163856..    311703: 147848:             last,eof

265120 is within 163856..311703 so this is the file! Or is it?

# hexdump -C --skip $((512*128*16570-163856*4096)) -n 32 firefox-network.log-main.2270 
18b90000  68 72 65 61 64 5d 3a 20  56 2f 6e 73 48 74 74 70  |hread]: V/nsHttp|
18b90010  20 30 30 30 30 33 44 31  30 3a 20 30 33 20 44 37  | 00003D10: 03 D7|
18b90020

The DNA matches, the timing works, everything checks out.

Of course I care about a practical solution: How can I list what is currently in dm-cache?

Unfortunately, this isn't very practical until you script it every step of the way. I have not been able to find a ready-to-use script for it. So all I can offer you at this point are the necessary ingredients. Sorry :-)

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .