Мне нужно понять, какие файлы потребляют iops моего жесткого диска. Просто использование «strace» не решит мою проблему. Я хочу знать, какие файлы действительно записываются на диск, а не в кеш страницы. Я попытался использовать «systemtap», но я не могу понять, как узнать, какие файлы (имена файлов или иноды) потребляют мои iops. Есть ли инструменты, которые помогут решить мою проблему?Как контролировать, какие файлы потребляют iops?
ответ
Возможно, iotop дает вам подсказку о том, какой процесс выполняет ввод-вывод, в результате у вас есть представление о связанных файлах.
iotop --only
--only опция используется для просмотра только процессов или потоков на самом деле делают ввода/вывода, вместо того чтобы показывать все процессы или потоки
Да, вы определенно можете использовать SystemTap для отслеживания этого. Когда верхний уровень (как правило, подсистема VFS) хочет выполнить операцию ввода-вывода, он будет вызывать функции submit_bio
и generic_make_request
. Обратите внимание, что это не обязательно означает одну операцию физического ввода-вывода. Например, записи из смежных секторов могут быть объединены планировщиком ввода-вывода.
Фокус в том, как определить путь к файлу в generic_make_request
. Это довольно просто для чтения, так как эта функция будет вызываться в том же контексте, что и вызов read()
. Пишу, как правило, асинхронные, так write()
будет просто обновить запись в кэше страницы и пометить его как грязный, в то время как submit_bio
вызывается одним из потоков ядра обратной записи, которые не имеют информации о первородном вызывающем процессе:
Пишет можно вывести, посмотрев на page
ссылка в bio
структура - есть mapping
из struct address_space
. struct file
что соответствует открытому файлу также содержит f_mapping
, который указывает на тот же экземпляр address_space и он также указывает на dentry
, содержащий имя файла (это может быть сделано с помощью task_dentry_path
)
Таким образом, мы должны были бы два датчика: один для захват пытается прочитать/записать файл и сохранить путь и address_space
в ассоциативный массив, а второй - для записи generic_make_request
вызовов (это выполняется с помощью зонда ioblock.request
).
Ниже приведен пример сценария, который считает IOPS:
// maps struct address_space to path name
global paths;
// IOPS per file
global iops;
// Capture attempts to read and write by VFS
probe kernel.function("vfs_read"),
kernel.function("vfs_write") {
mapping = $file->f_mapping;
// Assemble full path name for running task (task_current())
// from open file "$file" of type "struct file"
path = task_dentry_path(task_current(), $file->f_path->dentry,
$file->f_path->mnt);
paths[mapping] = path;
}
// Attach to generic_make_request()
probe ioblock.request {
for (i = 0; i < $bio->bi_vcnt ; i++) {
// Each BIO request may have more than one page
// to write
page = $bio->bi_io_vec[i]->bv_page;
mapping = @cast(page, "struct page")->mapping;
iops[paths[mapping], rw] <<< 1;
}
}
// Once per second drain iops statistics
probe timer.s(1) {
println(ctime());
foreach([path+, rw] in iops) {
printf("%3d %s %s\n", @count(iops[path, rw]),
bio_rw_str(rw), path);
}
delete iops
}
Этот пример скрипт работает для XFS, но должен быть обновлен для поддержки AIO и менеджеры томов (в том числе Btrfs). Кроме того, я не уверен, как он будет обрабатывать метаданные чтения и записи, но это хорошее начало;)
Если вы хотите узнать больше о SystemTap вы можете проверить мою книгу: http://myaut.github.io/dtrace-stap-book/kernel/async.html