Skip to main content
Email Password   helpLost your password?

Introduction

Directory Change Notification is the functionality provided by file system, which allows a file system user application to keep a watch on a directory residing on that file system. With this functionality, the file system user application will be notified whenever there is a change in the directory, which is being watched for. Applications can put a watch on a directory for certain changes such as File addition, deletion, or attributes changes like last modify time changes etc, and gets notified by file system, whenever any of these change occur.

Although this functionality is not mandatory for a file system to provide, yet there are certain applications which rely on Directory Change Notification support in a file system either completely or partially. Few of them are ASP.net, Internet Information Server (IIS), and few components of Microsoft Exchange (SMTP Service), Apache Web Server etc. Windows explorer also relies on this functionality to refresh its view whenever there is a change in directory, without this functionality, when changes to files occur by other processes in a directory, the changes will not be automatically reflected until a manual refresh is done or the file folder is reopened.

Whenever any application registers itself for directory change notification, file system receives IRP_MJ_DIRECTORY_CONTROL request with MinorFunction = IRP_MN_NOTIFY_CHANGE_DIRECTORY.

There are also few file system specific helper routines provided with Windows, which can be used to implement this functionality in a file system, few of them are: FsRtlNotifyFullChangeDirectory, FsRtlNotifyFullReportChange, FsRtlNotifyCleanup

This article explains how file system driver (FSD) can provide implementation for directory change notification feature and usage of this feature by user mode application.

How to implement directory notification in a file system driver?

Before proceeding with directory notification implementation for file systems, we will take a look at important data structures: FSD needs to maintain 2 important members per File System Volume:

This list is initialized to NULL and NotifySync object is initialized by calling FsRtlNotifyInitializeSync() function.

Following are steps to implement directory notification feature:

IrpSp->Parameters.NotifyDirectory.Length: Length in bytes of the buffer pointed to by Irp->UserBuffer.

IrpSp->Flags: If IrpSp->Flags is set to SL_WATCH_TREE, it means that all subdirectories of this directory also need to be watched. This value is later on utilized while calling FsRtlNotifyFullChangeDirectory()

Pseudo code for IRP_MN_NOTIFY_CHANGE_DIRECTORY handler looks as follows:< /P>

    BOOLEAN queuedSuccessfully = FALSE;
    completionFilter = IrpSp->Parameters.NotifyDirectory.CompletionFilter;
    watchTree = BooleanFlagOn( IrpSp->Flags, SL_WATCH_TREE );

    // We will be handling this request only for directories

    if (NotDirectory(IrpSp->FileObject))
    {
        // Complete request with STATUS_INVALID_PARAMETER

        ...
    }
    // Do all necessary validation


    // Call FsRtlNotifyFullChangeDirectory

    try
    {
        FsRtlNotifyFullChangeDirectory( 
                                    VolumeContext->NotifySync,
                &VolumeContext->DirNotifyList,
                IrpSp->FileObject->FsContext2,
                (PSTRING)&FileObjectContext->FullFileName,
                WatchTree,
                FALSE,
                CompletionFilter,
                Irp,
                NULL,
                NULL );
                Status = STATUS_PENDING;
        queuedSuccessfully = TRUE;
    } finally {
        // If something failed in between then complete the

        // request with unsuccessful status

        if (!queuedSuccessfully) {
            ...
        }
    }
    return Status;

In addition to this, file system driver needs to call FsRtlNotifyFullChangeDirectory with NotifyIRP = NULL, while handling close request for a directory, where a directory is created with FILE_DELETE_ON_CLOSE create option. Whenever NotifyIRP is supplied as NULL, FsRtlNotifyFullChangeDirectory checks for all pending notify IRPs related to this file object and completes them with STATUS_DELETE_PENDING.

When changes occurs to any directory, file system should invoke FsRtlNotifyFullReportChange() function to inform the library about the changes. The library routine is then responsible for scanning all pending notify requests and processing them pertaining to particular event.

For e.g.: Let's consider a scenario where new subdirectory is added to a directory. Then after successful completion of subdirectory, file system needs to call FsRtlNotifyFullReportChange as follows:

 
FsRtlNotifyFullReportChange(
   VolumeContext->NotifySync,
   & VolumeContext->NotifyIrpList,
   (PSTRING)&FileObjectContext->FullNameDCN,
   (USHORT)( FileObjectContext->FullNameDCN.Length � NameForDCN.Length),
   (PSTRING)NULL,
   (PSTRING)NULL,
   (ULONG)FILE_NOTIFY_CHANGE_DIR_NAME,
   (ULONG)FILE_ACTION_ADDED,
   (PVOID)NULL );

[Please refer table from section "Different scenarios where FsRtl� is called" for possible values of FilterMatch and Action parameter and appropriate scenarios where they are used]

Whenever Cleanup is performed on a particular file object (indicating all user handles for given file objects are closed), File system should notify the FSRTL using FsRtlNotifyCleanup()function. FSRTL library then dequeues and completes all Notify IRPs related to this file object.

Below is example of FsRtlNotifyCleanup usage inside IRP_MJ_CLEANUP handler:

if(!NotDirectory(IrpSp->FileObject))
{
    FsRtlNotifyCleanup(VolumeContext->NotifySync,
        &VolumeContext->NotifyIrpList,
        IrpSp->FileObject->FsContext2);
}

Different scenarios where FsRtlFullReportChange is called

Below is the table which summarizes different directory change scenarios where FSD need to call FsRtlFullReportChange and related value for "FilterMatch" and "Action" parameters:

No.

Scenario

File System IRP(s)

FilterMatch

Action

1

A subdirectory is deleted

IRP_MJ_CLEANUP

FILE_NOTIFY_CHANGE_DIR_NAME

FILE_ACTION_REMOVED

2

File is deleted

IRP_MJ_CLEANUP

FILE_NOTIFY_CHANGE_FILE_NAME

FILE_ACTION_REMOVED

3

New subdirectory is created

IRP_MJ_CREATE

FILE_NOTIFY_CHANGE_DIR_NAME

FILE_ACTION_ADDED

4

New File is created

IRP_MJ_CREATE

FILE_NOTIFY_CHANGE_FILE_NAME

FILE_ACTION_ADDED

5

File / Directory attributes are modified

IRP_MJ_SET_INFORMATION,

FILE_NOTIFY_CHANGE_ATTRIBUTES

FILE_NOTIFY_CHANGE_SIZE

FILE_NOTIFY_CHANGE_LAST_WRITE

FILE_NOTIFY_CHANGE_LAST_ACCESS

FILE_NOTIFY_CHANGE_CREATION

FILE_ACTION_MODIFIED

6

File size changed during write operation

IRP_MJ_WRITE

FILE_NOTIFY_CHANGE_SIZE

FILE_ACTION_MODIFIED

7

End-Of-File for a file is modified

IRP_MJ_SET_EA

FILE_NOTIFY_CHANGE_EA

FILE_ACTION_MODIFIED

8

Security attributes for a file are modified

IRP_MJ_SET_SECURITY

FILE_NOTIFY_CHANGE_SECURITY

FILE_ACTION_MODIFIED

Reporting directory changes for Rename operation

Rename operation needs special handling. In this case there are 2 notifications events needs to set:

First event when source directory is deleted for object being renamed:

If rename is performed within a same directory and target of rename operation does not exists then FSD should report FILE_ACTION_RENAMED_OLD_FILE else the FSD should report FILE_ACTION_REMOVED.

Second event related to target object of rename operation:

There can 3 possible scenarios:

How to register user mode application for directory notification?

An application can register for directory change notification by calling FindFirstChangeNotification() function.

- FindFirstChangeNotification() function takes "dwNotifyFilter" as an argument so that application can wait for particular directory changes. Also, "bWatchSubtree" argument decides whether or not to monitor the directory sub tree.

- After calling "FindFirstChangeNotification", application waits for change notification, this is done by calling WaitForMultipleObjects or WaitForSingleObject function.

- Once first wait is satisfied, FindNextChangeNotification can be used to provide a notification handle to wait on subsequent changes.

- The FindCloseChangeNotification function closes the notification handle.

- Similar to FindFirstChangeNotification, wait functions are called after the FindNextChangeNotification function to wait for directory change event.

Below is sample source code which waits for directory notification for "C:\" -

#include <windows.h>

#include <stdio.h>

int main()
{
    DWORD dwWaitStatus;
    HANDLE dwChangeHandles[1];
    dwChangeHandles[0] = FindFirstChangeNotification(
    "C:",     // directory to watch

    FALSE,              // do not watch the subtree

    FILE_NOTIFY_CHANGE_DIR_NAME); 
    // watch Dir name changes

   
    if (dwChangeHandles[0] == INVALID_HANDLE_VALUE)
        exit(GetLastError());
    printf("Watching C:\ for directory changes\n");
    // Change notification is set. Now wait on both notifications

    // handles and refresh accordingly.

    while (TRUE) {
        dwWaitStatus = WaitForMultipleObjects(1, dwChangeHandles,
            FALSE, INFINITE);
        printf(".")
        switch (dwWaitStatus) {
            case WAIT_OBJECT_0:
        if (FindNextChangeNotification( dwChangeHandles[0]) 
            == FALSE )
                exit(GetLastError());
                    default:
                printf( "Notify message failure\n");
                exit(0);
                break;
        }
    }
    return 0;
}

Directory Change Notification Support in a Distributed File System

Providing support for Directory Change Notification in a distributed file systems becomes a little bit more challenging because of the global name space nature of the file system, which gets accessed by multiple nodes, so if a directory has been modified by one node, then it should notify all other nodes, about the change and nature of change.

So it is required to have following functionality support in a distributed file system protocol to provide Directory Change Notification functionality:

Notify all nodes regarding change, this notification message will contain Notification structure describing exact change

- As soon as a node receives such change message, it calls FsRtlNotifyFullReportChange by extracting appropriate parameters from notification structure sent with message.

Even after placing the notification mechanism in place, it some times become almost impossible to accurately implement Directory Change Notification functionality in Distributed file systems, because of the inherent network delay of notification message exchange.

So one has to make a choice between their needs and based on that makes the decision up to what extent, one wants to provide Directory Change Notification support in Distributed File System.

References

Installable File System Design Guide

http://msdn2.microsoft.com/en-us/library/ms793583.aspx

Windows NT File System Internals � Design Guide

You must Sign In to use this message board.
 
 
Per page   
 FirstPrevNext
GeneralMy vote of 1 Pin
-midiman-
10:28 20 Dec '08  
GeneralRe: My vote of 1 Pin
Pratima Kudale
16:31 1 Mar '09  
GeneralIFS kit documentation and PSDK provide more structured detail then this. Pin
harishfor
1:15 19 Nov '08  
GeneralHow to use? Pin
Hans Dietrich
14:34 13 Jul '07  
GeneralCool Info Pin
Vishu Gurav
10:28 12 Jul '07  
GeneralWeird looking article Pin
sk8er_boy287
6:28 12 Jul '07  


Last Updated 12 Jul 2007 | Advertise | Privacy | Terms of Use | Copyright © CodeProject, 1999-2009