string_get_size()でサイズのお手軽表示

この記事はLinux Advent Calendar 2017の22日目の記事です。 カーネルのコードを書いていてサイズを表示したい時にstring_get_size()を使うとお手軽に2進接頭辞(KiBとか)とSI接頭辞(KBとか)を使ったサイズの文字列を作ることができます。

関数のプロトタイプはこうです。

void string_get_size(u64 size, u64 blk_size, enum string_size_units units,
             char *buf, int len);

sizeとblk_sizeは使い分けが有ります。バイト数を扱いたい場合はsizeにバイト数、blk_sizeには1を指定します。ブロックデバイスやページなどを扱う場合などはそのサイズをblk_sizeに指定して、それがいくつあるかをsizeで指定します。

たとえば、1024という数字を2進接頭辞にするならsizeには1024、blk_sizeは1をセットします。1ページのサイズが4096バイトで1ページのバイト数を2進接頭辞にするならsizeは1、blk_sizeは4096という感じです。 unitsは2進接頭辞かSI接頭辞を指定します。bufに渡した変数に結果が入ります。lenはbufで利用可能なバイト数ですね。

こんな感じで使えます。

#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/string_helpers.h>

MODULE_DESCRIPTION("size test");
MODULE_AUTHOR("masami256");
MODULE_LICENSE("GPL");

struct size_test_data {
    u64 size;
    u64 blk_size;
    int unit;
};

static struct size_test_data data[] = {
    {
        .size = 1024,
        .blk_size = 1,
        .unit = STRING_UNITS_2,
    },
    {
        .size = 1024,
        .blk_size = 1,
        .unit = STRING_UNITS_10,
    },
    {
        .size = 1,
        .blk_size = 4096,
        .unit = STRING_UNITS_2,
    },
    {
        .size = 1,
        .blk_size = 4096,
        .unit = STRING_UNITS_10,
    }
};

static int size_test_init(void)
{
    int i;

    for (i = 0; i < sizeof(data) / sizeof(data[0]); i++) {
        char buf[16] = { 0 };
        struct size_test_data tmp = data[i];
        string_get_size(tmp.size, tmp.blk_size, tmp.unit, buf, sizeof(buf) - 1);
        pr_info("size:%lld, blk_size: %lld, unit:%d,  %s\n",
            tmp.size, tmp.blk_size,
            tmp.unit, buf);
    }

    return 0;
}

static void size_test_cleanup(void)
{
    pr_info("%s bye\n", __func__);
}

module_init(size_test_init);
module_exit(size_test_cleanup);

実行するとこう表示されます。

[ 1402.100472] size_test: size:1024, blk_size: 1, unit:1,  1.00 KiB                                      
[ 1402.100474] size_test: size:1024, blk_size: 1, unit:0,  1.02 kB                                       
[ 1402.100474] size_test: size:1, blk_size: 4096, unit:1,  4.00 KiB                                      
[ 1402.100475] size_test: size:1, blk_size: 4096, unit:0,  4.10 kB  

地味に便利ですね( ´ー`)フゥー...