英語で読む

次の方法で共有


Windows オフロード データ転送

ODX (オフロード データ転送) は、サーバーのコピー操作と移動操作を高速化する機能です。 この機能は Windows Server 2012 以降で使用でき、NTFS ボリュームでサポートされています。 このページでは、ファイル システムとミニフィルターの観点から ODX について説明します。 ストレージ デバイスに関連する情報については「Windows 記憶域オフロード データ転送」を参照してください。

コンピューター間または同じコンピューター内でデータを転送することは、ファイル システムの頻繁なアクティビティです。 標準の ReadFile 関数と WriteFile 関数を使用すると、機能の観点からは適切に機能しますが、システムのすべてのレベルを介して、ネットワーク経由で大量のデータ移動が必要になります。 この複雑性は、転送に関係するシステムの可用性と、システムを接続するネットワークに影響を与える可能性があります。 多くのストレージ サブシステムで利用できる高度な機能により、データ移動の「高負荷の処理」タスクをより効率的に実行できます。

アプリケーションはこれらの機能を利用して、データ移動のプロセスをストレージ サブシステムにオフロードするのに役立ちます。 通常、ファイル システム フィルターでは、ボリュームへの読み取り要求と書き込み要求を傍受することで、これらのアクションを監視できます。 フィルターで ODX を認識するには、さらに多くのアクションが必要です。

一般的なデータ転送

現在のアプリケーション シナリオでのデータの移動はより簡単です。 データをローカル メモリに読み取り、新しい場所に書き戻す必要があります。 次の図にこのシナリオを示します。

一般的なデータ転送の図。

このシナリオでは、2 つの異なるファイル サーバー上の 2 つの場所の間でファイルをコピーします。それぞれに「インテリジェントな記憶域配列 (ISA)」 を介して公開される独自の仮想ディスクがあります。 開始システムはまず、ソース仮想ディスクからローカル バッファーにデータを読み取る必要があります。 次に、データをパッケージ化し、何らかのトランスポートとプロトコル(SMB over 1 GbE など) を介して 2 番目のシステムに送信します。 次に、2 番目のシステムが、データを受け取り、ローカル バッファーに出力します。 次に、ターゲット システムは、コピー先の仮想ディスクにデータを書き込みます。 このシナリオでは、多くの異なるアプリケーションによって毎日複数回実行される、一般的なデータ転送の読み取り/書き込みメソッドについて説明します。

標準の読み取りと書き込みはほとんどのシナリオで適切に機能しますが、コピーするデータは、同じインテリジェントな記憶域配列によって管理される仮想ディスクに配置される可能性があります。 つまり、この状況ではデータは配列から、サーバー上、ネットワーク トランスポート経由で、別のサーバーに移動され、同じ配列にもう一度移動されます。 サーバー内およびネットワーク トランスポート間でデータを移動する動作は、これらのシステムの可用性に大きく影響する場合があります。 さらに、データ移動のスループットは、ネットワークのスループットと可用性によって制限されます。

オフロード データ転送 (ODX)

データ転送のオフロード

Windows 8 では、データ転送をオフロードするメソッドを容易にする 2 つの FSCTL が導入されました。 このオフロードにより、ビット移動の負荷がサーバーから、ストレージ サブシステム内でインテリジェントに発生するビット移動に移ります。 コマンド セマンティクスを視覚化する最善の方法は、バッファーなし読み取りとバッファーなし書き込みに似たものとして考える方法です。

  • FSCTL_OFFLOAD_READ

    この制御要求は、読み取るファイル内のオフセットと、FSCTL_OFFLOAD_READ_INPUT 構造体の目的の長さを受け取ります。 サポートされている場合、ファイルをホストするストレージ サブシステムは、関連付けられているオフロード読み取りストレージ コマンドを受け取ります。 次に、オフロード読み取りコマンドの時点で読み取られるデータの論理表現であるトークンを生成します。 このトークン文字列は、FSCTL_OFFLOAD_READ_OUTPUT 構造体の呼び出し元に返されます。

  • FSCTL_OFFLOAD_WRITE

    この制御要求は、書き込むファイル内のオフセット、書き込みの目的の長さ、および書き込むデータの論理表現であるトークンを受け取ります。 サポートされている場合、書き込まれるファイルをホストするストレージ サブシステムは、関連付けられているオフロード書き込みストレージ コマンドを受け取ります。 最初に特定のトークンを認識し、可能であれば書き込み操作を実行します。 書き込み操作は Windows の下で完了するため、ファイル システムとストレージ スタック上のコンポーネントではデータの移動は表示されません。 データ移動が完了すると、書き込まれたバイト数が呼び出し元に返されます。

最初の図と同様に、次の図は、2 つの異なるサーバー上の 2 つの仮想ディスク間の単純なファイル コピーを示しています。

オフロード データ転送を示す図。

ただし、通常の読み取りと書き込みを行う代わりに、ビット移動の高負荷の作業を記憶域配列にオフロードします。 最初のシステムはオフロード読み取り操作を発行し、最初の仮想ディスクの領域内で読み取られるデータの特定の時点のビューを表すトークンを生成するように配列に要求します。 その後、最初のシステムはトークンを 2 番目のシステムに送信し、次にトークンを使用して 2 番目の仮想ディスクにオフロード書き込み操作を発行します。 その後、配列はトークンを解釈し、仮想ディスク間のデータ移動を実行しようとします。 実際のデータ転送は、2 つのホスト間ではなく、インテリジェントな記憶域配列内で行われます。 この設計によっり、システム間のネットワーク トラフィックを実質的に排除しながら、2 つのシステムの可用性が大幅に向上します。

コピー エンジンとの統合

Windows のコア コピー エンジンは、CopyFile および関連する関数によって使用されます。 Windows 8 以降、コピー エンジンは、従来のコピー ファイル コード パスの前に ODX を透過的に使用しようとします。 copy API は、ほとんどのアプリケーション、ユーティリティ、およびシェルで使用されます。 これらの呼び出し元は、コードの変更やユーザーの介入をほとんど行わず、既定で ODX 機能を使用できます。

次の手順は、コピー エンジンが ODX を試行する方法をまとめたものです。

  1. コピー エンジンは、ソース ファイルに FSCTL_OFFLOAD_READ を発行して、読み取りトークンを取得します。
  2. 読み取りトークンの取得に失敗した場合、コピー エンジンは従来の読み取りと書き込み (従来のコピー ファイル のコード パス) にフォールバックします。 ソース ボリュームがオフロードをサポートしていないことを示すエラーの場合、コピー エンジンはプロセスごとのキャッシュ内のボリュームもマークします。 コピー エンジンは、プロセスごとのキャッシュ内のボリュームに対してそれ以上オフロードを試行しません。
  3. トークンが正常に取得された場合、コピー エンジンは、トークンによって論理的に表されるすべてのデータがオフロードで書き込まれるまで、ターゲット ファイルに対して FSCTL_OFFLOAD_WRITE コマンドを大きなチャンクで発行しようとします。
  4. オフロード読み取り/書き込みの実行でエラーが発生すると、コピー エンジンが従来の読み取り/書き込みコード パスにフォールバックします。 このフォールバックは、オフロード コード パスが終了した場所 (読み取りまたは書き込みが切り捨てられた場所) から開始されます。 コピー エンジンは、次のいずれかの条件に該当する場合、これらのボリュームでオフロードを試行しないように、同じプロセスごとのキャッシュを更新します。 このプロセスごとのキャッシュは定期的にリセットされます。
  • このエラーは、宛先ボリュームがオフロードをサポートしていないことを示します。
  • ソース ボリュームが宛先ボリュームに到達できません。

次の関数が ODX に対応しています。

  • CopyFile
  • CopyFileEx
  • MoveFile
  • MoveFileEx
  • CopyFile2

次の関数は ODX に対応していません。

  • CopyFileTransacted
  • MoveFileTransacted

サポートされているオフロード データ転送シナリオ

オフロード操作のサポートは、Hyper-V ストレージ スタックと Windows SMB ファイル サーバーで提供されます。 バッキング物理ストレージが ODX 操作をサポートしている場合、呼び出し元は、仮想マシン内から、または物理ハードウェア上のどちらからでも、VHD またはリモート ファイル共有に存在するファイルに対して FSCTL_OFFLOAD_READFSCTL_OFFLOAD_WRITE を発行できます。 次の図は、ODX でサポートされている最も基本的なコピー元ターゲットとコピー先ターゲットを示しています。

オフロード データ転送のシナリオを示す図。

ファイル システム フィルターオプトイン モデルとアプリケーションへの影響

Windows 8 以降では、フィルター マネージャーを使用して、サポートされている機能としてオフロード機能を指定できます。 ボリュームに接続されたファイル システム フィルターは、特定のオフロード操作がサポートされているかどうかをまとめて判断できます。 サポートされていない場合、操作は適切なエラー コードで失敗します。

フィルターは、HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\filter driver name\のレジストリのドライバー サービス定義にある SupportedFeatures という名前のレジストリ DWORD 値を使用して、FSCTL_OFFLOAD_READFSCTL_OFFLOAD_WRITE をサポートしていることを示す必要があります。 この値には、ビットがオプトインする機能を決定し、フィルターのインストール時に設定する必要があるビット フィールドが含まれます。

現在、定義されているビットは次のとおりです。

フラグ 意味
SUPPORTED_FS_FEATURES_OFFLOAD_READ 0x00000001 フィルターは FSCTL_OFFLOAD_READ をサポートします
SUPPORTED_FS_FEATURES_OFFLOAD_WRITE 0x00000002 フィルターは FSCTL_OFFLOAD_WRITE をサポートします

フィルターオプトイン モデルは、次の値を持つ HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\FileSystem\FilterSupportedFeaturesMode レジストリ キーに存在する値に基づいて有効または無効にすることができます。

FilterSupportedFeaturesMode 値 意味
0 (既定値) 通常のオプトイン処理を行います。
1 オプトインしない (接続されているすべてのフィルターで SupportedFeatures を 0 に設定することと同じ)

テスト

スタックのフィルターでサポートされている機能をチェックするには、fltmc ユーティリティを使用します。 fltmc インスタンス –v [volume]: を管理者特権ユーザーとして実行し、SprtFtrs 列をチェックします。

  • SprtFtrs 値が 0x00 場合は、フィルターがこのボリュームのオフロードをブロックしていることを意味します。 SprtFtrs が 0x03 に設定されている場合、両方のオフロード操作がサポートされます。

IRP 処理での機能サポートの確認

IRP 処理の一環として、 FsRtlGetSupportedFeatures ルーチンは、指定されたボリューム スタックに接続されているすべてのフィルターの集計された SupportedFeatures 状態を取得します。 I/O Manager や SRV (SMB) などのコンポーネントは、このルーチンを呼び出して、スタック上のすべてのフィルターの SupportedFeatures 状態を検証します。 独自のオフロード IRP をロールするコンポーネントは、この関数を呼び出して、その操作のオプトイン サポートを検証する必要があります。

フィルター ドライバーに関する考慮事項

ODX は、データ センター内でデータを移動する方法です。 コア コピー エンジンでのオフロード ロジックの統合により、多くのアプリケーションでは、既定では、明示的にオプトインすることなくオフロードされたデータ移動を実行できます。 その結果、フィルター開発者は、これらの新しい操作がフィルターに与える影響を理解する必要があります。 これらの操作を完全に理解していないか、データ フローへの変更を評価しないと、データが不整合になったり破損したりする可能性があります。 次の一覧は、フィルター開発者がオフロードで注意すべきアクション項目のセットをまとめたものです。

  • このデータ フロー、フィルターへの影響、およびこれらのオフロードされた操作をサポートするフィルターの機能について説明します。
  • フィルター インストーラーを更新して、SupportedFeatures の REG_DWORD 値を HKLM\System\CurrentControlSet\Services\[filter] サブキーに追加します。 オフロード機能を指定するために初期化します。
  • オフロード操作に対応するフィルターの場合は、登録を更新して、FSCTL_OFFLOAD_READFSCTL_OFFLOAD_WRITE を処理するように IRP_MJ_FILE_SYSTEM_CONTROL します。
  • オフロードされた操作をブロックする必要があるフィルターの場合は、フィルター内から STATUS_NOT_SUPPORTED 状態コードを返します。 エンド ユーザーが変更できるため、オフロード操作のブロックを強制するためにレジストリ値に依存しないでください。 フィルターでは、オフロード操作を明示的に許可または禁止する必要があります。

トークンのコピー

オフロード操作では、ファイル データは、I/O スタックに表示されません。 代わりに、ファイル データは、データの論理プロキシである 512 バイト のトークンと見なされます。 このトークンは次のいずれかです。

  • ストレージ サブシステムによって生成されるベンダー固有の形式の不透明で一意の文字列。
  • データのパターンを表す既知の型 (論理的に 0 と等価なデータ範囲など)。

プロキシ トークンのデータを修正することで、トークンが無効化されるか、スナップショット メカニズムのようなベンダー固有の方法によってストレージ サブシステムが元のデータを永久化します。 後続の読み取り要求をファイル内の指定された範囲にオフロードすると、一意のトークンが生成されます。

適切に定義されたデータのパターンを表すトークンのクラスがあります。 最も一般的な既知のトークンは、0 に相当する「ゼロ トークン」です。 トークンが既知のトークンとして定義されている場合、STORAGE_OFFLOAD_TOKEN 構造体の TokenType メンバーは STORAGE_OFFLOAD_TOKEN_TYPE_WELL_KNOWNに 設定されます。 このフィールドを設定すると、 WellKnownPattern メンバーによって、トークンがどのパターンのデータであるかが決まります。

  • WellKnownPattern フィールドが STORAGE_OFFLOAD_PATTERN_ZERO または STORAGE_OFFLOAD_PATTERN_ZERO_WITH_PROTECTION_INFORMATION に設定されている場合は「ゼロ トークン」を示します。 このトークンが FSCTL_OFFLOAD_READ 操作によって返される場合、目的のファイル範囲内に含まれるデータが論理的に 0 と等価であることを示します。 このトークンが FSCTL_OFFLOAD_WRITE 操作に提供されると、書き込むファイルの目的の範囲を論理的に 0 にする必要があることを示します。
  • 「ゼロ トークン」以外に、現在定義されている既知のトークン パターンは他にありません。 ユーザーが独自の既知のトークン パターンを定義することはお勧めしません。

切り捨て

Windows が通信する基になるストレージ サブシステムでは、オフロード操作で必要なデータの処理が少なくなります。 この条件は切り捨てと呼ばれます。 オフロード読み取りでは、返されたトークンは、要求されたデータよりも小さいデータの範囲を表します。 FSCTL_OFFLOAD_READ_OUTPUT 構造体の TransferLength メンバーは、この値を示すために使用されます。この値は、読み込まれるファイルの範囲の先頭からのバイト数です。 オフロード書き込みの場合、切り捨ては、書き込まれたデータが必要以上に少ないことを示します。 FSCTL_OFFLOAD_WRITE_OUTPUT 構造体の LengthWritten メンバーは、この値を示します。この値は、書き込まれるファイルの範囲の先頭からのバイト数です。 コマンド処理中のエラー、またはスタック内の大きな範囲の制限により、切り捨てが発生します。

NTFS が読み取りまたは書き込みをオフロードする範囲を切り捨てるシナリオは 2 つあります。

  1. VDL がファイルの末尾 (EOF) の前にある場合、コピー範囲は有効なデータ長 (VDL) に切り捨てられます。 このアクションは、VDL が論理セクター境界に整列されていることを前提としています。それ以外の場合はシナリオを参照してください。

    EOF より前に発生している VDL を示す図。

    FSCTL_OFFLOAD_READ 操作中に、ファイルの残りの部分に 0 が含まれていることを示す FSCTL_OFFLOAD_READ_OUTPUT 構造体にフラグ OFFLOAD_READ_FLAG_ALL_ZERO_BEYOND_CURRENT_RANGE が設定され、TransferLength メンバーが VDL に切り捨てられます。

  2. シナリオ 1 と同様ですが、VDL が論理セクター境界に整列されていない場合、NTFS は、目的の範囲を次の論理セクター境界に切り捨てます。

    VDL がセクター境界とずれている様子を示す図。

制限事項

  • オフロード操作は、NTFS ボリュームでのみサポートされます。
  • 次の条件が両方とも当てはまる場合、オフロード操作はリモート ファイル サーバーを介してサポートされます。
    • リモート共有は NTFS ボリュームです。
    • サーバーは Windows Server 2012 以降のバージョンを実行しています (リモート スタックでもオフロード操作がサポートされていると仮定します)。
  • NTFS では、Bitlocker または NTFS 暗号化 (EFS)、重複除去ファイル、圧縮ファイル、常駐ファイル、スパース ファイル、TxF トランザクションに参加しているファイルで暗号化されたファイルに対して実行されるオフロード FSCTL はサポートされていません。
  • NTFS では、volsnap スナップショット内のファイルに対して実行されるオフロード FSCTL はサポートされていません。
  • 次のいずれかの条件が満たされている場合、NTFS はオフロード FSCTL に失敗します。 この方法は、キャッシュされていない IO と同じセマンティクスに従います。
    • 目的のファイル範囲は、ソース デバイスの論理セクター サイズに合わせて調整されません。
    • 目的のファイル範囲は、接続先デバイスの論理セクター サイズに合わせて調整されません。
  • FSCTL_OFFLOAD_WRITE する前に、コピー先ファイルを事前に割り当てる必要があります (SetAllocation ではなく SetEndOfFile)。
  • NTFS が、オフロード読み取りと書き込みを処理する場合、最初に CcCoherencyFlushAndPurgeCache を呼び出して、システム キャッシュで修正されたデータをコミットします。 このアクションは、非キャッシュ IO と同じセマンティックです。