編集

編集

btrfs サブボリューム上のファイルを stat すると、メジャー デバイス番号が取得されます0。このデバイスが btrfs サブボリュームであることを事前に知らなくても、このデバイスのマウント ポイントを見つける確実な方法はありますか?

たとえば、Python でこれを実行できるようにしたいと思います。

>>> st = os.stat('a file')
>>> os.major(st.st_dev)
0
>>> os.minor(st.st_dev)
38
>>> os.path.exists('/sys/dev/block/0:38')
False
>>> magic_method_that_gets_mount_point(0, 38)
'/home'
>>> magic_method_that_gets_mount_point(8, 1)
'/boot'

(私の場合、sda1( /sys/dev/block/8:1) は にマウントされており/boot/homeの btrfs サブボリュームですsda2)。

編集

ファイルのパスを知らなくてもこれを実行できる必要があります。上記ではos.stat例として使用しましたが、情報は実際にはioctlループ デバイスの呼び出しから取得され、次の結果が返されます。

struct loop_info64 {
    uint64_t    lo_device;
    uint64_t    lo_inode;
    uint64_t    lo_rdevice;
    uint64_t    lo_offset;
    uint64_t    lo_sizelimit;
    uint32_t    lo_number;
    uint32_t    lo_encrypt_type;
    uint32_t    lo_encrypt_key_size;
    uint32_t    lo_flags;
    uint8_t     lo_file_name[64];
    uint8_t     lo_crypt_name[64];
    uint8_t     lo_encrypt_key[32];
    uint64_t    lo_init[2];
};

フィールドはありますlo_file_nameが、最大長は 63 文字なので、オープンであるとは限らないことに注意してください。 についても認識しています/sys/block/loopX/loop/backing_fileが、これは Linux >= 2.6.37 でのみ使用可能であり、私のコードは CentOS 6 (2.6.32) で実行する必要があります。

編集#2

ここでの私の最終的な目標は、ループデバイスのバッキングファイルを確実に見つけられるようにすることです。util-linuxでさえ、カーネル2.6.37未満ではこれを実行できません。

> dd if=/dev/urandom bs=4096 count=256 of=/root/a_really_really_really_really_really_really_really_long_file_name.img
256+0 records in
256+0 records out
1048576 bytes (1.0 MB) copied, 0.137397 s, 7.6 MB/s
> LD=`losetup -f --show /root/a_really_really_really_really_really_really_really_long_file_name.img`
> losetup $LD
/dev/loop1: [fd00]:922372 (/root/a_really_really_really_really_really_really_really_long_*)

ファイル名が切り捨てられていることに注意してください。これは、util-linux がloop_info64フィールドに 63 文字の制限がある構造体を使用するためですlo_file_name

確実に取得できるのは、デバイス ID とバッキング ファイルの inode 番号です。バッキング ファイルは btrfs サブボリュームに保存されているため、ここで行き詰まりました。

答え1

私は Gnu core-utils のソースコード、特にdfコマンドを調べました。

デバイス ID が変更されるまで、階層を再帰的に下っていきます。ID が変更されるポイントがマウント ポイントです。

ファイルシステムのマウント ポイントを見つけようとしました~/home/me/a-dir/another-dir。次のようにしました:

stat . #noting device IDs
while id not changes and root not hit
do
  cd ..
  stat .
done
if root not hit
then
  cd -
fi

(このコードは疑似 bash であり、すべての条件とループは手動で実行されています。これは概念を証明するためのものです。プログラミングと Python への翻訳は読者の練習として残しておきます。)

関連情報