Windows オフロード データ転送

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

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

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

一般的なデータ転送

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

typical data transfer.

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

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

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

データ転送のオフロード

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

  • FSCTL_OFFLOAD_READ

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

  • FSCTL_OFFLOAD_WRITE

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

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

offloaded data transfer.

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

コピー エンジンとの統合

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

次の手順は、コピー エンジンがオフロードされたデータ転送を試みる方法をまとめたものです。

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

次の関数は、オフロードされたデータ転送をサポートします。

  • CopyFile
  • CopyFileEx
  • MoveFile
  • MoveFileEx
  • CopyFile2

次の関数は、オフロードされたデータ転送をサポートしていません。

  • CopyFileTransacted
  • MoveFileTransacted

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

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

offloaded data transfer scenarios.

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

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 をロールするコンポーネントは、この関数を呼び出して、その操作のオプトイン サポートを検証する必要があります。

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

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

  • このデータ フロー、フィルターへの影響、およびこれらのオフロードされた操作をサポートするフィルターの機能について説明します。
  • フィルター インストーラーを更新して、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 が論理セクター境界に整列されていることを前提としています。それ以外の場合はシナリオを参照してください。

    vdl occurring before eof.

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

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

    vdl misaligned with sector boundary.

制限事項

  • オフロード操作は、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 と同じセマンティックです。