Чтение устаревших данных файла с помощью debugfs cat

Чтение устаревших данных файла с помощью debugfs cat

Я пытаюсь прочитать содержимое файла, используя его inode.

Это работает отлично:

echo "First line" > data.txt
sync
sudo debugfs -R "cat <$(stat -c %i data.txt)>" /dev/sda3

debugfs сообщает мне, что содержимое файла — «Первая строка». Эта часть команды получает номер inode data.txt: $(stat -c %i data.txt).

При добавлении второй строки все идет наперекосяк:

echo "Second line" >> data.txt
sync
sudo debugfs -R "cat <$(stat -c %i data.txt)>" /dev/sda3

Я все еще получаю только "Первую строку" от debugfs. Это не меняется после добавления дополнительных строк, syncповторного запуска или повторной попытки через пару дней.

Почему debugfs не показывает оставшуюся часть содержимого файла? Я неправильно использую debugfs?

Я могу с уверенностью воспроизвести это поведение с другими файлами.


Я заметил, что при перезаписи существующего содержимого файла с помощью echo "New content" > data.txtdebugfs показывает новое содержимое. Но добавление к нему второй строки, как описано выше, покажет только первую строку.


Я работаю на Arch Linux 5.12.3 с debugfs 1.46.2. Файловая система /dev/sda3ext4. Вызов debugfs -R "stat ..."выдает следующее, что мне кажется не подозрительным:

Inode: 16515371   Type: regular    Mode:  0644   Flags: 0x80000
Generation: 3923658711    Version: 0x00000000:00000001
User:  1000   Group:  1000   Project:     0   Size: 34
File ACL: 0
Links: 1   Blockcount: 8
Fragment:  Address: 0    Number: 0    Size: 0
ctime: 0x60b639e5:71315fa0 -- Tue Jun  1 15:45:09 2021
atime: 0x60b63988:b7c456cc -- Tue Jun  1 15:43:36 2021
mtime: 0x60b639e5:71315fa0 -- Tue Jun  1 15:45:09 2021
crtime: 0x60b63988:b7c456cc -- Tue Jun  1 15:43:36 2021
Size of extra inode fields: 32
Inode checksum: 0xbfa4390e
EXTENTS:
(0):66095479

решение1

Это из-за кэширования. У вас есть как минимум два варианта.

  1. Используйте -Dфлаг:

    -D Заставляет debugfs открывать устройство с помощью прямого ввода-вывода, минуя буфер.
    fer кэш. Обратите внимание, что некоторые устройства Linux, в частности, устройство сопоставления, как
    в этом тексте не поддерживается прямой ввод-вывод.
    

  2. Удалить кэш буфера:

    echo 1 | sudo tee /proc/sys/vm/drop_caches
    

См. например:


Если вы не передадите флаг, -Dвы все равно сможете увидеть некоторые действия, передав результат, например xxd:

sudo debugfs -R "cat <$(stat --printf %i data.txt)>" /dev/sda3 | xxd -a -c 32

Вы увидите, чтоcatФайл заполняется нулевыми байтами, а иногда и данными (если записано достаточно).

Например, после того, какecho A >data.txt

00000000: 410a                A.

Затем после for i in {1..7}; do echo A >>data.txt; done:

00000000: 410a 0000 0000 0000 0000 0000 0000 0000  A...............

Вы также можете осуществлять мониторинг, используя что-то вроде этого:

Использование:sudo ./script file_to_monitor

Он запускается watchсо awkскриптом, который печатает статистику для устройства, а /sys/blockтакже печатает результат cat <inode>для файла.

#!/bin/sh

if [ "$1" = "-h" ]; then
    printf '%s FILE\n' "$0"
    exit 1
fi

file="$1"
inode=$(stat --printf %i "$file")
dev_path="$(df -P -- "$file" | awk 'END{print $1}')"
dev_name="$(lsblk -no NAME  "$dev_path")"
dev_core="$(lsblk -no PKNAME  "$dev_path")"

if [ "$dev_core" = "loop" ]; then
    fn_stat=/sys/block/$dev_name/stat
else
    fn_stat=/sys/block/$dev_core/$dev_name/stat
fi

printf 'File : %s\n' "$file"
printf 'Inode: %s\n' "$inode"
printf 'Stat : %s\n' "$fn_stat"
printf 'Dev  : %s\n' "$dev_path"

printf "Continue? [yN] " >&2
read -r ans
if ! [ "$ans" = "y" ] && ! [ "$ans" = "Y" ]; then
    exit
fi

watch -n 0.2 'awk \
    -v inode="'$inode'" \
    -v dev_path="'$dev_path'" \
"{
    rs = \$3 * 512
    rsk = rs / 1024
    rsm = rsk / 1024
    ws = \$7 * 512
    wsk = ws / 1024
    wsm = wsk / 1024

    printf \" 1: Reads  Completed   : %9d\n\", \$1
    printf \" 2: Reads  Merged      : %9d\n\", \$2
    printf \" 3: Read   Sectors     : %9d %6d MiB %9d KiB %d bytes\n\",
    \$3, rsm, rsk, rs
    printf \" 4: Read   ms          : %9d\n\", \$4
    printf \" 5: Writes Completed   : %9d\n\", \$5
    printf \" 6: Writes Merged      : %9d\n\", \$6
    printf \" 7: Write  Sectors     : %9d %6d MiB %9d KiB %d bytes\n\",
    \$7, wsm, wsk, rs
    printf \" 8: Write  ms          : %9d\n\", \$8
    printf \" 9: I/Os   in progress : %9d\n\", \$9
    printf \"10: I/O    ms          : %9d\n\", \$10
    printf \"11: I/O    ms weighted : %9d\n\", \$11

    printf \"\n\nFILE <%d> %s:\n\", inode, dev_path

    system(\"sudo debugfs -R '\''cat <\"inode\">'\'' \"dev_path\" | xxd -a -c 32\")
}
"' "$fn_stat"

Связанный контент