3

最初のブロックデバイスにマウント時にデータが含まれ、もう一方が空であると見なされるように、2つのブロックデバイスを新しいブロックデバイスにバインドするカーネルモジュールの開発に興味があります。すべての書き込みは2番目のパーティションに対して行われるため、次のマウントではベースファイルシステムは変更されません。私はUnionFSのようなソリューションを知っていますが、それらはファイルシステムベースですが、それをより低い層のブロックベースで開発したいと思っています。

カーネルモジュールから広告読み取り/書き込みブロックデバイスを開く方法を教えてもらえますか?おそらく、マージされたブロックデバイスの読み取り/書き込みにユーザースペースプログラムを使用せずに。ここで同様のトピックを見つけましたが、filp​​_ *関数は(大きな)ブロックデバイスI / Oではなく、小さな構成ファイルを読み取るためのものであるため、答えはかなり満足のいくものではありませんでした。

ブロックデバイスを作成するためのインターフェイスは標準化されているため、ソースデバイスを実装する関数に直接(またはほぼ直接)アクセスすることを考えていました。とにかく同様の関数をエクスポートするように要求されるためです。それができれば、ソースデバイスで適切な関数を呼び出すプロキシ関数を作成するだけです。どういうわけか、別のドライバーに属するgendisk構造へのポインターを取得できますか?

これは私自身の目的にしか役立たないので(それらの主なものであるクオリオシティを満たす)、私はカーネルを真剣に台無しにすることを心配していません。

または、そのようなモジュールがすでに存在するかどうか誰かが知っていますか?

4

3 に答える 3

4

dmの/mdブロックデバイスのコードを調べることを検討してください。drivers/mdこれらの既存のドライバーは、他のブロックデバイスにデータを格納するブロックデバイスを作成します。

実際、あなたはおそらくあなたのアイデアを別の「RAIDパーソナリティ」として実装しmd、それによってデバイスをセットアップするために既存のユーザースペースツールを利用することができます。

于 2010-12-13T11:42:35.570 に答える
4

デバイスマッパードライバーのソースコードは、ニーズに適合します。Linux / drivers / md /dm-*のLinuxソースのコードを見てください。

他のデバイスのgendisk構造にアクセスする必要はありませんが、その要求キューにアクセスする必要があります。I / Oリクエストを準備し、それを他のデバイスのキューにプッシュすることができ、それが残りを自動的に実行します。

別のブロックデバイスを開く単純なブロックデバイスを実装しました。それを説明している私の投稿を見てください: stackbd:別のブロックデバイスの上にブロックデバイスをスタックする

別のデバイスのgendiskにアクセスするために必要な関数の例を次に示します。パス( "/ dev /")を使用して別のブロックデバイスを開く方法:

struct block_device *bdev_raw = lookup_bdev(dev_path);
printk("Opened %s\n", dev_path);
if (IS_ERR(bdev_raw))
{
    printk("stackbd: error opening raw device <%lu>\n", PTR_ERR(bdev_raw));
    return NULL;
}
if (!bdget(bdev_raw->bd_dev))
{
    printk("stackbd: error bdget()\n");
    return NULL;
}
if (blkdev_get(bdev_raw, STACKBD_BDEV_MODE, &stackbd))
{
    printk("stackbd: error blkdev_get()\n");
    bdput(bdev_raw);
    return NULL;
}

あるデバイスから別のデバイスにI/O要求を渡す最も簡単な例は、変更せずに再マッピングすることです。次のコードで、bi_bdevエントリが別のデバイスで変更されていることに注意してください。ブロックアドレス(* bi_sector)とデータ自体を変更することもできます。

static void stackbd_io_fn(struct bio *bio)
{
    bio->bi_bdev = stackbd.bdev_raw;

    trace_block_bio_remap(bdev_get_queue(stackbd.bdev_raw), bio,
            bio->bi_bdev->bd_dev, bio->bi_sector);

    /* No need to call bio_endio() */
    generic_make_request(bio);
}
于 2014-11-01T07:18:20.470 に答える
0

あなたがGPLされたカーネルモジュールなら、カーネルモードからopen()、read()、write()などを呼び出すことができますよね?

もちろん、この方法には、ハンドルが存在するためのスペースを作成するためにカーネルモードからフォークする必要があるなどの特定の注意事項があります。

于 2010-12-13T04:38:12.580 に答える