Requête et octroi d'oplocks
Lorsque le redirecteur réseau accède aux fichiers sur des serveurs distants, il demande l’oplock à partir du serveur distant. Les applications clientes demandent directement des oplocks uniquement lorsque le verrou est destiné à un fichier sur le serveur local.
Les Oplocks sont requis par l'intermédiaire des FSCTL. Les fichiers FSCTL suivants sont utilisés pour les différents types d’oplocks , que les applications en mode utilisateur et les pilotes en mode noyau peuvent émettre.
- Pour demander des oplocks Windows 7 :
- Pour la requête d'anciens oplocks :
Requête d'un Oplock en mode utilisateur
Pour demander un oplock Windows 7 en mode utilisateur, appelez DeviceIoControl:
- Attribuez la valeur FSCTL_REQUEST_OPLOCK à dwIoControlCode.
- Passez un pointeur vers une structure REQUEST_OPLOCK_INPUT_BUFFER dans le paramètre lpInBuffer.
- Reportez-vous à la documentation de cette structure pour plus d’informations sur la mise en forme de la demande d’oplock.
- Passez un pointeur vers une structure REQUEST_OPLOCK_OUTPUT_BUFFER dans le paramètre lpOutBuffer.
Pour plus d'informations, voir FSCTL_REQUEST_OPLOCK.
Si l’oplock demandé peut être accordé, DeviceIoControl retourne FALSE et GetLastError retourne ERROR_IO_PENDING. C'est pourquoi les oplocks ne sont jamais accordés pour les E/S synchrones. L'opération chevauchée ne se termine pas tant que l'oplock n'est pas rompu. Une fois l'opération terminée, le REQUEST_OPLOCK_OUTPUT_BUFFER contient des informations sur l'interruption de l'oplock.
Si l’oplock ne peut pas être accordé, le système de fichiers retourne un code d’erreur approprié. Les codes d’erreur les plus couramment retournés sont ERROR_OPLOCK_NOT_GRANTED et ERROR_INVALID_PARAMETER.
Requête d'un Oplock en mode noyau
Pour la requête des oplocks de Windows 7 en mode noyau :
Minifilters du système de fichiers
Un minifiltre de système de fichiers doit utiliser FltAllocateCallbackData et remplir la FLT_CALLBACK_DATA allouée comme suit :
- Attribuez la valeur IRP_MJ_FILE_SYSETM_CONTROL à son champ >Iopb-MajorFunction.
- Attribuer la valeur IRP_MN_USER_FS_REQUEST à son champ Iopb->MinorFunction.
- Attribuez la valeur FSCTL_REQUEST_OPLOCK> à son membre Iopb-Parameters.FileSystemControl.Buffered.FsControlCode.
- Alloue un tampon dont la taille est égale à la plus grande des deux valeurs suivantes : REQUEST_OPLOCK_INPUT_BUFFER ou REQUEST_OPLOCK_OUTPUT_BUFFER.
- Définissez le membre Iopb->Parameters.FileSystemControl.Buffered.SystemBuffer du FLT_CALLBACK_DATA alloué pour qu'il pointe vers ce tampon.
- Définissez les champs Iopb->Parameters.FileSystemControl.Buffered.InputBufferLength et Iopb-Parameters.FileSystemControl.Buffered.OutputBufferLength> du FLT_CALLBACK_DATA alloué à la taille de ce tampon.
Reportez-vous à la documentation de la structure REQUEST_OPLOCK_INPUT_BUFFER pour obtenir des informations sur le formatage de la requête oplock.
Ensuite, le minifiltre du système de fichiers doit appeler FltPerformAsynchronousIo, en passant le paramètre FLT_CALLBACK_DATA alloué comme CallbackData.
Si l'oplock demandé peut être accordé, l'appel FltPerformAsynchronousIo renvoie STATUS_PENDING. C'est pourquoi les oplocks ne sont jamais accordés pour les E/S synchrones. L'opération ne se termine pas tant que l'oplock n'est pas rompu. Une fois l'opération terminée, le REQUEST_OPLOCK_OUTPUT_BUFFER contient des informations sur l'interruption de l'oplock.
Si l’oplock ne peut pas être accordé, le système de fichiers retourne un code d’erreur approprié. Les codes d’erreur les plus couramment retournés sont STATUS_OPLOCK_NOT_GRANTED et STATUS_INVALID_PARAMETER.
Autres types de pilotes
D’autres types de pilotes peuvent appeler ZwFsControlFile:
- Mettez FsControlCode à FSCTL_REQUEST_OPLOCK.
- Passez un pointeur sur une structure REQUEST_OPLOCK_INPUT_BUFFER dans le paramètre InputBuffer et fixez le paramètre InputBufferLength à la taille de ce tampon.
- Passez un pointeur sur une structure REQUEST_OPLOCK_OUTPUT_BUFFER dans le paramètre OutputBuffer et fixez le paramètre OutputBufferLength à la taille de ce tampon.
Reportez-vous à la documentation de la structure REQUEST_OPLOCK_INPUT_BUFFER pour plus d’informations sur le formatage de la requête d'oplock.
Si l'oplock demandé peut être accordé, l'appel ZwFsControlFile renvoie STATUS_PENDING. C'est pourquoi les oplocks ne sont jamais accordés pour les E/S synchrones. L'opération ne se termine pas tant que l'oplock n'est pas rompu. Une fois l'opération terminée, le REQUEST_OPLOCK_OUTPUT_BUFFER contient des informations sur l'interruption de l'oplock.
Si l’oplock ne peut pas être accordé, le système de fichiers retourne un code d’erreur approprié. Les codes d’erreur les plus couramment retournés sont STATUS_OPLOCK_NOT_GRANTED et STATUS_INVALID_PARAMETER.
Éviter les violations de partage lors de la requête d'oplocks
Utilisation de la méthode Atomic Create-With-Oplock
Atomic create-with-oplock n’est pas un type oplock, il s’agit d’une procédure qui permet aux opérations ouvertes d’éviter de provoquer des violations en mode partage dans le temps entre l’ouverture d’un fichier et la réception d’un oplock. Avec les anciens oplocks, cela n'est possible qu'avec les oplocks de filtrage et nécessite l'ouverture de deux handles. Avec windows 7 oplocks, une application ou un pilote peut demander n’importe quel type d’oplock à l’aide de cette procédure et n’a besoin d’ouvrir qu’un seul handle.
Pour exécuter la procédure atomique de création avec oplock, vous devez procéder comme suit :
- Utilisez fltCreateFileEx2 ou ZwCreateFile, le cas échéant, pour ouvrir le fichier. Dans le paramètre CreateOptions, passez l'indicateur FILE_OPEN_REQUIRING_OPLOCK. Vous pouvez définir les paramètres DesiredAccess et ShareAccess comme vous le souhaitez. Par exemple, dans le paramètre DesiredAccess, définissez GENERIC_READ pour pouvoir lire le fichier, et dans le paramètre ShareAccess, définissez les indicateurs FILE_SHARE_READ | FILE_SHARE_DELETE pour permettre à d'autres personnes de lire, de renommer et/ou de marquer le fichier pour suppression pendant que vous l'avez ouvert.
- Utilisez le code de contrôle FSCTL_REQUEST_OPLOCK pour demander un oplock sur l'objet ou le handle de fichier résultant, comme décrit ci-dessus dans la section Demander un oplock en mode noyau.
Remarque
Vous ne devez effectuer aucune opération de système de fichiers sur le fichier entre les étapes 1 et 2. Cela peut entraîner des interblocages.
L’oplock le plus courant à demander à l’aide de cette procédure est le type Read-Handle. Cela vous permet d'accorder aux autres appelants autant d'accès simultanés que possible, tout en vous permettant d'être averti si vous devez fermer votre handle pour éviter de causer une violation de partage à un open conflictuel.
Utilisation de l'ancien oplock de filtrage
L'ancien oplock Filter permet également à une application de « se retirer » lorsque d'autres applications/clients tentent d'accéder au même flux, mais il est moins souple que la méthode atomique create-with-oplock (créer avec oplock). Ce mécanisme permet à une application d’accéder à un flux sans provoquer d’autres accesseurs du flux à recevoir des violations de partage lors de la tentative d’ouverture du flux. Pour éviter les violations de partage, la procédure suivante en trois étapes doit être utilisée pour la requête d'un oplock de filtrage :
Ouvrez le fichier avec un accès obligatoire de FILE_READ_ATTRIBUTES et un mode de partage de FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE. Le handle ouvert dans cette étape n’entraîne pas que d’autres applications reçoivent des violations de partage, car elles sont ouvertes uniquement pour l’accès aux attributs (FILE_READ_ATTRIBUTES) et non pour l’accès aux données (FILE_READ_DATA). Cette poignée est adaptée à la requête d'un sas de filtrage, mais pas à l'exécution d'E/S sur le flux de données.
Demandez un oplock de filtrage (FSCTL_REQUEST_FILTER_OPLOCK) sur le handle de l'étape 1. L'oplock accordé à cette étape permet au détenteur de l'oplock de « s'écarter du chemin » sans causer de violation de partage à une autre application qui tente d'accéder au flux.
Ouvrez à nouveau le fichier pour l’accès en lecture. Le handle ouvert à cette étape permet au détenteur de l'oplock d'effectuer des entrées/sorties sur le flux.
Le système de fichiers NTFS optimise cette procédure grâce à l'indicateur d'option de création FILE_RESERVE_OPFILTER. Si cet indicateur est spécifié à l’étape 1 de la procédure précédente, il permet au système de fichiers d’échouer la demande de création avec STATUS_OPLOCK_NOT_GRANTED si le système de fichiers peut déterminer que l’étape 2 échouera. Si l’étape 1 réussit, il n’existe aucune garantie que l’étape 2 réussit, même si FILE_RESERVE_OPFILTER a été spécifiée pour la demande de création.
Conditions d'octroi des oplocks
Le tableau suivant identifie les conditions nécessaires à l'octroi d'un oplock.
Type de requête | Conditions |
---|---|
Niveau 1 Filtre Batch |
Accordé uniquement si toutes les conditions suivantes sont remplies :
Si l'état actuel de l'oplock est :
|
Niveau 2 |
Accordé uniquement si toutes les conditions suivantes sont remplies :
Si l'état actuel de l'oplock est :
|
Lire |
Accordé uniquement si toutes les conditions suivantes sont remplies :
Si l'état actuel de l'oplock est :
|
Poignée de lecture |
Accordé uniquement si toutes les conditions suivantes sont remplies :
Si l'état actuel de l'oplock est :
|
Lecture-écriture |
Accordé uniquement si toutes les conditions suivantes sont remplies :
Si l'état actuel de l'oplock est :
|
Lecture-écriture |
Accordé uniquement si toutes les valeurs suivantes sont vraies :
Si l'état actuel de l'oplock est :
|
Remarque
Les oplocks de lecture et de niveau 2 peuvent coexister sur le même flux, de même que les oplocks de lecture et de gestion de lecture, mais les oplocks de niveau 2 et de gestion de lecture ne peuvent pas coexister.