oplock の要求と許可

ネットワーク リダイレクタは、リモート サーバー上のファイルにアクセスするときに、リモート サーバーに oplock を要求します。 クライアント アプリケーションは、ロックがローカル サーバー上のファイルを対象とする場合にのみ、oplock を直接要求します。

OplocksFSCTLs.を通じてリクエストされます。 次の FSCTL はさまざまな用途に使用されます oplock の種類、ユーザー モード アプリケーションとカーネル モード ドライバーの両方が発行できます。

ユーザー モードで Windows 7 oplock を要求するには、デバイスIoControl を呼び出します:

同様の方法で、カーネル モードで Windows 7 oplock を要求するには、次のようにします。

4 つの Windows 7 oplock のうちどれが必要かを指定するには、REQUEST_OPLOCK_INPUT_BUFFER 構造の RequestedOplockLevel を 1 つ以上を設定します。

  • OPLOCK レベル キャッシュの読み取り
  • OPLOCK レベル キャッシュ ハンドル
  • OPLOCK レベル キャッシュ書き込み

詳細については、FSCTL_REQUEST_OPLOCK を参照してください。

要求された oplock が許可される場合、ファイル システムは STATUS_PENDING を戻します。 このため、同期 I/O に対して oplock は決して許可されません。 FSCTL IRP は、oplock が解除されるまで完了しません。

oplock を付与できない場合、ファイル システムは適切なエラー コードを戻します。 最も一般的に返されるエラー コードは、STATUS_OPLOCK_NOT_GRANTED および STATUS_INVALID_PARAMETER (およびそれらと同等のユーザー モード類似コード) です。

フィルター oplock を使用すると、他のアプリケーション/クライアントが同じストリームにアクセスしようとしたときに、アプリケーションが「バックアウト」できます。 このメカニズムにより、アプリケーションは、ストリームを開こうとするときに、ストリームの他のアクセサーが共有違反を受け取ることなく、ストリームにアクセスできます。 共有違反を回避するには、特別な 3 ステップの手順を使用してフィルター oplock (FSCTL_REQUEST_FILTER_OPLOCK) を要求する必要があります。

  1. 必要なアクセスは FILE_READ_ATTRIBUTES で、共有モードは FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE です。

  2. ステップ 1 のハンドルに対してフィルター oplock を要求します。

  3. 読み取りアクセスのためにファイルを再度開きます。

手順 1 で開いたハンドルは、データ アクセス (FILE_READ_DATA) ではなく、属性アクセス (FILE_READ_ATTRIBUTES) に対してのみ開かれるため、他のアプリケーションが共有違反を受けることはありません。 このハンドルは、フィルター oplock の要求には適していますが、データ ストリーム上で実際の I/O を実行する場合には適していません。 ステップ 3 で開いたハンドルにより、oplock の所有者はストリームに対して I/O を実行できるようになります。 手順 2 で oplock を付与すると、oplock の所有者は、ストリームにアクセスしようとする別のアプリケーションに共有違反を引き起こすことなく「邪魔にならないように」できます。

NTFS ファイル システムは、FILE_RESERVE_OPFILTER 作成オプション フラグを通じてこのプロシージャを最適化します。 このフラグが前の手順のステップ 1 で指定されている場合、ファイル システムがステップ 2 が失敗すると判断できれば、ファイル システムは STATUS_OPLOCK_NOT_GRANTED で作成リクエストを失敗できます。 ステップ 1 が成功した場合、作成リクエストに FILE_RESERVE_OPFILTER が指定されていたとしても、ステップ 2 が成功する保証はありません。

次の表は、oplock を許可するために必要な条件を示しています。

要求の種類 条件

レベル 1

Assert

Batch

これは、次の条件がすべて満たされている場合にのみ当てはまります。

  • リクエストは、ファイルの特定のストリームに対するものです。
    • ディレクトリの場合は、STATUS_INVALID_PARAMETERが戻されます。
  • ストリームは ASYNCHRONOUS アクセス用に開かれます。
    • SYNCHRONOUS アクセス用に開かれた場合、STATUS_OPLOCK_NOT_GRANTED が返されます (oplock は同期 I/O 要求には許可されません)。
  • TxF ファイルの任意のストリーム上のトランザクションはありません。
    • それ以外のSTATUS_OPLOCK_NOT_GRANTEDが返されます。
  • ストリーム上には (同じスレッドによるものであっても) 他のオープンはありません。
    • それ以外のSTATUS_OPLOCK_NOT_GRANTEDが返されます。

現在の oplock 状態が次の場合:

  • oplock なし: リクエストは許可されます。

  • レベル 2: 元のレベル 2 リクエストは FILE_OPLOCK_BROKEN_TO_NONE で壊れています。 その後、要求された排他的 oplock が許可されます。

  • レベル 1、バッチ、フィルター、読み取り、読み取りハンドル、読み取り書き込み、または読み取り書き込みハンドル: STATUS_OPLOCK_NOT_GRANTED が返されます。

レベル 2

これは、次の条件がすべて満たされている場合にのみ当てはまります。

  • リクエストは、ファイルの特定のストリームに対するものです。
    • ディレクトリの場合は、STATUS_INVALID_PARAMETERが戻されます。
  • ストリームは ASYNCHRONOUS アクセス用に開かれます。
    • 同期アクセス用に開かれた場合は、STATUS_OPLOCK_NOT_GRANTEDが返されます。
  • ファイルには TxF トランザクションがありません。
    • それ以外のSTATUS_OPLOCK_NOT_GRANTEDが返されます。
  • ストリームには現在のバイト範囲ロックがありません。
    • それ以外のSTATUS_OPLOCK_NOT_GRANTEDが返されます。
    • Windows 7 より前のバージョンでは、オペレーティング システムは、ストリームが最後に開かれて以来、ストリーム上にバイト範囲ロックが存在したかどうかを確認し、存在する場合は要求を失敗します。

現在の oplock 状態が次の場合:

  • oplock なし: リクエストは許可されます。

  • レベル 2 または読み取り: 要求が許可されます。 同じストリームに複数のレベル 2/読み取り oplock を同時に付与できます。 複数のレベル 2 (読み取りではない) oplock が同じハンドル上に存在することもできます。
    • すでに読み取り oplock が付与されているハンドルに対して読み取り oplock が要求された場合、最初の読み取り oplock の IRP は STATUS_OPLOCK_SWITCHED_TO_NEW_HANDLE で完了してから、2 番目の読み取り oplock が付与されます。
  • レベル 1、バッチ、フィルター、読み取りハンドル、読み取り書き込み、読み取り書き込みハンドル: STATUS_OPLOCK_NOT_GRANTED が返されます。

読み込み

これは、次の条件がすべて満たされている場合にのみ当てはまります。

  • リクエストは、ファイルの特定のストリームに対するものです。
  • ストリームは ASYNCHRONOUS アクセス用に開かれます。
    • 同期アクセス用に開かれた場合は、STATUS_OPLOCK_NOT_GRANTEDが返されます。
  • ファイルには TxF トランザクションがありません。
    • それ以外のSTATUS_OPLOCK_NOT_GRANTEDが返されます。
  • ストリームには現在のバイト範囲ロックがありません。
    • それ以外のSTATUS_OPLOCK_NOT_GRANTEDが返されます。

現在の oplock 状態が次の場合は注意してください。

  • oplock なし: リクエストは許可されます。

  • レベル 2 または読み取り: 要求が許可されます。 同じストリームに複数のレベル 2/読み取り oplock を同時に付与できます。
    • さらに、既存の oplock が新しいリクエストと同じ oplock キーを持っている場合、その IRP は STATUS_OPLOCK_SWITCHED_TO_NEW_HANDLE で完了します。
  • Read-Handle と既存の oplock には、新しいリクエストとは異なる oplock キーがあります。リクエストは許可されます。 複数の読み取り oplock と読み取りハンドル oplock は同じストリーム上に共存できます (この表の後の注を参照)。
    • それ以外の場合 (oplock キーが同じ)、STATUS_OPLOCK_NOT_GRANTED が返されます。
  • レベル 1、バッチ、フィルター、読み取り/書き込み、読み取り/書き込みハンドル: STATUS_OPLOCK_NOT_GRANTED が返されます。

読み取りハンドル

これは、次の条件がすべて満たされている場合にのみ当てはまります。

  • リクエストは、ファイルの特定のストリームに対するものです。
  • ストリームは ASYNCHRONOUS アクセス用に開かれます。
    • 同期アクセス用に開かれた場合は、STATUS_OPLOCK_NOT_GRANTEDが返されます。
  • ファイルには TxF トランザクションがありません。
    • それ以外のSTATUS_OPLOCK_NOT_GRANTEDが返されます。
  • ストリームには現在のバイト範囲ロックがありません。
    • それ以外のSTATUS_OPLOCK_NOT_GRANTEDが返されます。

現在の oplock 状態が次の場合:

  • oplock なし: リクエストは許可されます。

  • 読み取り: リクエストは許可されます。
    • 既存の読み取り oplock に新しいリクエストと同じ oplock キーがある場合、その IRP は STATUS_OPLOCK_SWITCHED_TO_NEW_HANDLE で完了します。 その結果、oplock は読み取りから読み取りハンドルにアップグレードされます。
    • 新しいリクエストと同じ oplock キーを持たない既存の読み取り oplock は変更されません。
  • レベル 2、レベル 1、バッチ、フィルター、読み取り/書き込み、読み取り/書き込みハンドル: STATUS_OPLOCK_NOT_GRANTEDが返されます。

読み取り/書き込み

これは、次の条件がすべて満たされている場合にのみ当てはまります。

  • リクエストは、ファイルの特定のストリームに対するものです。
    • ディレクトリの場合は、STATUS_INVALID_PARAMETERが戻されます。
  • ストリームは ASYNCHRONOUS アクセス用に開かれます。
    • 同期アクセス用に開かれた場合は、STATUS_OPLOCK_NOT_GRANTEDが返されます。
  • ファイルには TxF トランザクションがありません。
    • それ以外のSTATUS_OPLOCK_NOT_GRANTEDが返されます。
  • ストリーム上に他のオープンがある場合 (同じスレッドによる場合でも)、それらは同じ oplock キーを持っている必要があります。
    • それ以外のSTATUS_OPLOCK_NOT_GRANTEDが返されます。

現在の oplock 状態が次の場合:

  • oplock なし: リクエストは許可されます。

  • 読み取りまたは読み取り/書き込みで、既存の oplock がリクエストと同じ oplock キーを持っています。既存の oplock の IRP が STATUS_OPLOCK_SWITCHED_TO_NEW_HANDLE で完了すると、リクエストは許可されます。
    • それ以外のSTATUS_OPLOCK_NOT_GRANTEDが返されます。
  • レベル 2、レベル 1、バッチ、フィルター、読み取りハンドル、読み取り書き込みハンドル: STATUS_OPLOCK_NOT_GRANTED が返されます。

読み取り/書き込みハンドル

次のすべてが当てはまる場合にのみ許可されます。

  • リクエストは、ファイルの特定のストリームに対するものです。
    • ディレクトリの場合は、STATUS_INVALID_PARAMETERが戻されます。
  • ストリームは ASYNCHRONOUS アクセス用に開かれます。
    • 同期アクセス用に開かれた場合は、STATUS_OPLOCK_NOT_GRANTEDが返されます。
  • ファイルには TxF トランザクションがありません。
    • それ以外のSTATUS_OPLOCK_NOT_GRANTEDが返されます。
  • ストリーム上に他のオープン要求がある場合 (同じスレッドによるものであっても)、それらは同じ oplock キーを持っている必要があります。
    • それ以外のSTATUS_OPLOCK_NOT_GRANTEDが返されます。

現在の oplock 状態が次の場合:

  • oplock なし: リクエストは許可されます。

  • Read、Read-Handle、Read-Write、または Read-Write-Handle であり、既存の oplock がリクエストと同じ oplock キーを持っている場合: 既存の oplock の IRP が STATUS_OPLOCK_SWITCHED_TO_NEW_HANDLE で完了すると、リクエストは許可されます。
    • それ以外のSTATUS_OPLOCK_NOT_GRANTEDが返されます。
  • レベル 2、レベル 1、バッチ、フィルター: STATUS_OPLOCK_NOT_GRANTED が返されます。

Note

読み取り oplock とレベル 2 oplock は同じストリーム上に共存でき、読み取り oplock と読み取りハンドル oplock は共存できますが、レベル 2 oplock と読み取りハンドル oplock は共存できません。