null

Получение размера ZFS-пула с точностью до байта

Если вы обратили внимание, утилиты для работы с zfs: zfs и zpool выводят все размерные характеристики: размер пула, квоты на файловую систему и т.п. в т.н. Human-Readable Format, то есть в мегабайтах и гигабайтах - десятичными дробями. Никакой опции для изменения подобного поведения не существует. Все дело в том, что административная библиотека libzfs всегда вызывает функцию zfs_nicenum:
libzfs_pool.c#270

Посмотрим, каким образом можно узнать точный размер пула. Для начала я обратился к mdb -k и его командам для работы со spa. Однако в самой структуре spa_t я не нашел поля, отвечающего за размер всего пула - только используя spa_config смог узнать размер VDEVов, в пул входящих:

> ::spa
ADDR         STATE NAME
e2693480    ACTIVE tank
> e2693480::spa_config
version=000000000000000a
name='tank'
<cut>
vdev_tree
    type='root'
    id=0000000000000000
    guid=46a625bc361d7d57
    children[0]
        type='disk'
    <cut>
        asize=0000000012a80000
        <cut>


Соответственно поле asize - и есть размер диска в VDEV.  Тогда я вспомнил, что в DTrace есть замечательный провайдер pid, служащий для отладки пользовательских приложений. Почему бы не воспользоваться им для выковыривания информации напрямую из libzfs?

Анализ кода показал, что для получения свойств пула (нам потребуется только имя и собственно размер) - вызывается функция zfs_get_prop: libzfs_pool.c#zpool_get_prop , второй параметр которой - номер свойства. 0 - ZPOOL_PROP_NAME - имя пула, 1 - ZPOOL_PROP_SIZE - его размер. Для получения непосредственно значений свойств вызываются zpool_get_prop_string и zpool_get_prop_int.

Создадим простой скрипт для получения данных:

#!/usr/sbin/dtrace -s

#pragma D option quiet

pid$target:libzfs:zpool_get_prop:entry
/arg1 == 1/
{
        self->getsize = 1;
}

pid$target:libzfs:zpool_get_prop:entry
/arg1 == 0/
{
        self->getname = 1;
}


pid$target:libzfs:zpool_get_prop_int:return
/self->getsize/
{
        printf(" - %d \n", arg1);
        self->getsize = 0;
}

pid$target:libzfs:zpool_get_prop_string:return
/self->getname/
{
        printf("%s", copyinstr(arg1));
        self->getname = 0;
}



Соответственно при вызове zpool_get_prop со значениями 0 или 1 будет установлен флаг self->getname и self->getsize соответственно. После этого сработают пробы на функции zpool_get_prop_string и zpool_get_prop_int. Они выведут необходимую информацию на пробе return и сбросят флаги.

Запускаем скрипт на команде zpool list:

root@tiger # dtrace -s /zpoolan.d -c 'zpool list'
NAME   SIZE   USED  AVAIL    CAP  HEALTH  ALTROOT
tank   298M   111K   298M     0%  ONLINE  -     
tank - 312475648                                
tank - 312475648  



Размер пула tank - 312 475 648 байт.

К списку статей

 

Интересуюсь по большей части системным анализом программного обеспечения: поиском багов и анализом неисправностей, а также системным программированием (и не оставляю надежд запилить свою операционку, хотя нехватка времени сказывается :) ). Программированием увлекаюсь с 12 лет, но так уж получилось, что стал я инженером.

Основная сфера моей деятельности связана с поддержкой Solaris и оборудования Sun/Oracle, хотя в последнее время к ним прибавились технологии виртуализации (линейка Citrix Xen) и всякое разное от IBM - от xSeries до Power. Учусь на кафедре Вычислительной Техники НИУ ИТМО.

See you...out there!

http://www.facebook.com/profile.php?id=100001947776045
https://twitter.com/AnnoyingBugs

Ничего не найдено. n is 0