使用flock來解決parted與udev競爭的問題

當塊設備被parted寫入後關閉時,udevd守護程序將調用BLKRRPART ioctl(通知內核重新讀取分區表),同時parted會自行調用BLKPG_DEL_PARTITIONBLKPG_ADD_PARTITION。這通常沒有問題,但當udevd設法在分區DELADD調用之間調用BLKRRPART時,有時會導致分區失敗,如下所示:

Error: Error informing the kernel about modifications to partition /dev/sda1 -- Device or resource busy.  This means Linux won't know about any changes you made to /dev/sda1 until you reboot -- so you shouldn't mount it or use it in any way before rebooting.
Error: Failed to add partition 1 (Device or resource busy)

或者在重新格式化分區的時候遇到另外一個報錯:

mkfs.vfat: unable to open /dev/vdc1p1: No such file or directory

跟蹤udev源碼可以看到:如果udev無法獲取排他鎖(flock(fd,LOCK_EX | LOCK_NB)),那麼就不會觸發BLKRRPART ioctl,反之就會觸發該ioctl
相關信息也更新在systemd/NEWS:

CHANGES WITH 214
  * As an experimental feature, udev now tries to lock the
       disk device node (flock(LOCK_SH|LOCK_NB)) while it
       executes events for the disk or any of its partitions.
       Applications like partitioning programs can lock the
       disk device node (flock(LOCK_EX)) and claim temporary
       device ownership that way; udev will entirely skip all event
       handling for this disk and its partitions. If the disk
       was opened for writing, the close will trigger a partition
       table rescan in udev's "watch" facility, and if needed
       synthesize "change" events for the disk and all its partitions.
       This is now unconditionally enabled, and if it turns out to
       cause major problems, we might turn it on only for specific
       devices, or might need to disable it entirely. Device Mapper
       devices are excluded from this logic.

翻譯成中文意思是:

  *作爲一項實驗性功能,udev現在嘗試在執行磁盤或其任何分區的事件時,
       鎖定磁盤設備節點(flock(LOCK_SH | LOCK_NB)),
       分區程序之類的應用程序可以鎖定
       磁盤設備節點(flock(LOCK_EX))並聲明爲臨時
       設備所有權的方式;udev將完全跳過
       處理該磁盤及其分區的所有事件。如果磁盤
       被打開進行寫操作,關閉時將觸發一個
       在udev的“監視”工具中的分區重新掃描,如果需要的話
       請自行同步磁盤及其所有分區的“更改”事件。
       現在已無條件啓用此功能,如果結果
       造成重大問題,我們可能僅針對特定情況將其打開
       設備,或者根據需要完全禁用它。設備映射器
       設備不具備這個功能。

所以針對之前遇到的parted(或者partprobe)與udev競爭的問題,在運行打開寫入模式設備的進程之前,獲取獨佔鎖是一種有效的解決方法,比如在腳本里面添加如下代碼就可以解決該問題:

    udevadm settle --timeout=150
    while [[ true ]]; do
        flock -s /dev/sdb parted -s -a minimal /dev/sdb mkpart primary 1s 7500000s && break
        sleep 1
    done
    udevadm settle --timeout=150
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章