Development

Debug

如何新增一個 Block device attribute 在 /sys 下面

最簡單的方式可以透過以下的 macro 來達成

DEVICE_ATTR(_name, _mode, _show, _store)

另外針對 bus 或是 class 等 /sys 位置,還有 BUS_ATTR 與 CLASS_ATTR 可使用,使用方式與 DEVICE_ATTR 大同小異

在參數的部分講解如下 _name:在 sys fs 下生成的檔案名稱 _mode:生成檔案的權限 _show:讀取的 callback function,影響 cat 這個檔案會顯示什麼 _store: 寫入的 callback function,寫入檔案發生什麼

show 的 callback function 的簡單範例如下

static ssize_t xxx_show(struct device *dev,struct device_attribute *attr, char *buf)
{
    return scnprintf(buf, PAGE_SIZE, "%d\n", XXX_flag);
}

關於這邊為什麼要用 scnprintf 而不是 snprintf,網路上有人做過研究 總結來說,snprintf 回傳的結果是 預期的字串長度(src 的長度) 而非實際寫入長度(可參考LWN),相反的 scnprintf 是回傳實際寫入的長度(可能 src 比 des 長,就會受限在 des 的長度),如果是要作為 function 回傳寫入字串的長度,scnprintf 就會是比較安全的選擇

store 的 callback function 的簡單範例如下

static ssize_t xxx_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
    if (!strncmp(buf, 0, &num))
        debug_on = false;
    else
        debug_on = true;
    return count;
}

當定義好 show 與 store function 之後,接著就需要定義 device attritube

static DEVICE_ATTR(xxx, 0666, xxx_show, xxx_store);

定義之後不會就這樣生效,還需要在 device init 的時候加上這麼一段

    ret = device_create_file(dev->device, &dev_attr_xxx);
    if (ret != 0) {
        dev_err(&pdev->dev,"Failed to create xxx sysfs files: %d\n", ret);
        return ret;
    }

並在 device exit 時加上

    device_remove_file(dev->device, &dev_attr_ioerror_debug);

Tracing

blktrace

Introduction

blktrace 可用於記錄與分析 block 層處理 IO 的狀態

Prerequisite

  • Enable CONFIG_BLK_DEV_IO_TRACE
  • Get userspace tool from git://git.kernel.org/pub/scm/linux/kernel/git/axboe/blktrace.git

Usage

在使用之前,需要先做以下兩件事

  • 開啟 tracing 後 kernel module 必須全部重 build
  • 進入 blktrace 的資料夾,進行 make,並將 blktrace 與 blkparse 抓到機器上面

進入機器之後需要檢查 debugfs file system 有沒有 mount 起來,如果沒有則需要執行

mount -t debugfs debugfs /sys/kernel/debug

接著先介紹最基本使用方式

blktrace -d <Target device> -o - | blkparse -i -

此時如何有 IO 到 device 就會出現如同以下的訊息

  <1>    <2>      <3>   <4>           <5>  <6> <7><8>       <9>
  8,0    3        1     0.000000000   697  G   W 223490 + 8 [kjournald]
  8,0    3        2     0.000001829   697  P   R [kjournald]
  8,0    3        3     0.000002197   697  Q   W 223490 + 8 [kjournald]
  8,0    3        4     0.000005533   697  M   W 223498 + 8 [kjournald]
  8,0    3        5     0.000008607   697  M   W 223506 + 8 [kjournald]
  8,0    3        6     0.000011569   697  M   W 223514 + 8 [kjournald]
  8,0    3        7     0.000014407   697  M   W 223522 + 8 [kjournald]
  8,0    3        8     0.000017367   697  M   W 223530 + 8 [kjournald]
  8,0    3        9     0.000020161   697  M   W 223538 + 8 [kjournald]
  8,0    3       10     0.000024062   697  D   W 223490 + 56 [kjournald]
  8,0    1       11     0.009507758     0  C   W 223490 + 56 [0]
  8,0    1       12     0.009538995   697  G   W 223546 + 8 [kjournald]
  8,0    1       13     0.009540033   697  P   R [kjournald]
  8,0    1       14     0.009540313   697  Q   W 223546 + 8 [kjournald]
  8,0    1       15     0.009542980   697  D   W 223546 + 8 [kjournald]
  8,0    1       16     0.013542170     0  C   W 223546 + 8 [0]

依序解析每一個欄位的意思為

  1. Device major, minor
  2. CPU ID
  3. Sequence number (用途不明)
  4. Time stamp
  5. PID
  6. Action
  7. RWBS field
  8. Start block + number of block
  9. Process name

關於 RWBS field 一共有以下數種

R: Read
W: Write
B: Barrier
S: Synchronous
N: (目前沒看到相關的定義)

而 action 方面還看的懂的部分約有以下數種

  • C: Complete,表示 IO 不論成功或是失敗,已經由下層 driver 處理完畢並回覆結果
  • D: Issued/Dispatch,表示 Block layer 這一層該做的工作都已經完成,並將 IO 遞交給底層 driver
  • I: Inserted,IO 已經被送入 IO scheduler 之類的地方等待進行處理
  • Q: Queued,block layer 準備把上層的 BIO queue 起來,從文件上面的說明,這個時候 IO 還沒有正式進到 block layer 之中。

其他還有一些 action 因為沒有看懂完全的用途,等未來有用到時再補上來

Reference

Event tracing

https://lwn.net/Articles/379903/ https://github.com/spotify/linux/blob/master/Documentation/trace/events.txt

results matching ""

    No results matching ""