diff --git a/src/sys/cleanup.c b/src/sys/cleanup.c index 21416162..9eaa8021 100644 --- a/src/sys/cleanup.c +++ b/src/sys/cleanup.c @@ -138,8 +138,12 @@ static NTSTATUS FspFsvolCleanup( else { if (FileDesc->DidSetMetadata) - /* invalidate the parent dir info */ - FspFileNodeInvalidateParentDirInfo(FileNode); + { + if (0 == FileNode->MainFileNode) + FspFileNodeInvalidateParentDirInfo(FileNode); + else + FspFileNodeInvalidateStreamInfo(FileNode); + } return STATUS_SUCCESS; /* FspFsvolCleanupRequestFini will take care of the rest! */ } @@ -153,24 +157,46 @@ NTSTATUS FspFsvolCleanupComplete( FSP_FSCTL_TRANSACT_REQ *Request = FspIrpRequest(Irp); PFILE_OBJECT FileObject = IrpSp->FileObject; FSP_FILE_NODE *FileNode = FileObject->FsContext; + FSP_FILE_DESC *FileDesc = FileObject->FsContext2; + ULONG NotifyFilter, NotifyAction; - /* if the file is being deleted do a change notification */ + ASSERT(FileNode == FileDesc->FileNode); + + /* do the appropriate change notification; also invalidate dirinfo/etc. caches */ if (Request->Req.Cleanup.Delete) { - FspFileNodeNotifyChange(FileNode, - FileNode->IsDirectory ? FILE_NOTIFY_CHANGE_DIR_NAME : FILE_NOTIFY_CHANGE_FILE_NAME, - FILE_ACTION_REMOVED); - - /* FspFileNodeNotifyChange also invalidates parent dir and volume info */ + NotifyFilter = FileNode->IsDirectory ? + FILE_NOTIFY_CHANGE_DIR_NAME : FILE_NOTIFY_CHANGE_FILE_NAME; + NotifyAction = FILE_ACTION_REMOVED; } else { - /* invalidate the parent dir info */ - FspFileNodeInvalidateParentDirInfo(FileNode); + /* do change notification for any metadata changes */ + NotifyFilter = 0; + if (Request->Req.Cleanup.SetAllocationSize) + NotifyFilter |= FILE_NOTIFY_CHANGE_SIZE; + if (Request->Req.Cleanup.SetArchiveBit) + NotifyFilter |= FILE_NOTIFY_CHANGE_ATTRIBUTES; +#if 0 + if (Request->Req.Cleanup.SetLastAccessTime) + NotifyFilter |= FILE_NOTIFY_CHANGE_LAST_ACCESS; +#endif + if (Request->Req.Cleanup.SetLastWriteTime) + NotifyFilter |= FILE_NOTIFY_CHANGE_LAST_WRITE; + NotifyAction = FILE_ACTION_MODIFIED; + } - /* if the file is being resized invalidate the volume info */ - if (FileNode->TruncateOnClose) - FspFsvolDeviceInvalidateVolumeInfo(IrpSp->DeviceObject); + if (0 != NotifyFilter) + FspFileNodeNotifyChange(FileNode, NotifyFilter, NotifyAction, TRUE); + else + { + if (FileDesc->DidSetMetadata) + { + if (0 == FileNode->MainFileNode) + FspFileNodeInvalidateParentDirInfo(FileNode); + else + FspFileNodeInvalidateStreamInfo(FileNode); + } } FSP_LEAVE_IOC("FileObject=%p", IrpSp->FileObject); diff --git a/src/sys/create.c b/src/sys/create.c index 4c698c04..b45ae50e 100644 --- a/src/sys/create.c +++ b/src/sys/create.c @@ -1024,7 +1024,8 @@ NTSTATUS FspFsvolCreateComplete( FspFileNodeSetFileInfo(FileNode, FileObject, &Response->Rsp.Overwrite.FileInfo, TRUE); FspFileNodeNotifyChange(FileNode, FILE_NOTIFY_CHANGE_LAST_WRITE | FILE_NOTIFY_CHANGE_ATTRIBUTES | FILE_NOTIFY_CHANGE_SIZE, - FILE_ACTION_MODIFIED); + FILE_ACTION_MODIFIED, + FALSE); FspFileNodeReleaseOwner(FileNode, Full, Request); @@ -1115,7 +1116,8 @@ static NTSTATUS FspFsvolCreateTryOpen(PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Re if (FILE_CREATED == Response->IoStatus.Information) FspFileNodeNotifyChange(FileNode, FileNode->IsDirectory ? FILE_NOTIFY_CHANGE_DIR_NAME : FILE_NOTIFY_CHANGE_FILE_NAME, - FILE_ACTION_ADDED); + FILE_ACTION_ADDED, + TRUE); FspFileNodeRelease(FileNode, Main); diff --git a/src/sys/driver.h b/src/sys/driver.h index c1d49319..447c7866 100644 --- a/src/sys/driver.h +++ b/src/sys/driver.h @@ -1344,7 +1344,9 @@ ULONG FspFileNodeStreamInfoChangeNumber(FSP_FILE_NODE *FileNode) FileNode = FileNode->MainFileNode; return FileNode->StreamInfoChangeNumber; } -VOID FspFileNodeNotifyChange(FSP_FILE_NODE *FileNode, ULONG Filter, ULONG Action); +VOID FspFileNodeInvalidateStreamInfo(FSP_FILE_NODE *FileNode); +VOID FspFileNodeNotifyChange(FSP_FILE_NODE *FileNode, ULONG Filter, ULONG Action, + BOOLEAN InvalidateCaches); NTSTATUS FspFileNodeProcessLockIrp(FSP_FILE_NODE *FileNode, PIRP Irp); NTSTATUS FspFileDescCreate(FSP_FILE_DESC **PFileDesc); VOID FspFileDescDelete(FSP_FILE_DESC *FileDesc); diff --git a/src/sys/file.c b/src/sys/file.c index 1f290c22..f75f9d57 100644 --- a/src/sys/file.c +++ b/src/sys/file.c @@ -74,9 +74,9 @@ BOOLEAN FspFileNodeReferenceStreamInfo(FSP_FILE_NODE *FileNode, PCVOID *PBuffer, VOID FspFileNodeSetStreamInfo(FSP_FILE_NODE *FileNode, PCVOID Buffer, ULONG Size); BOOLEAN FspFileNodeTrySetStreamInfo(FSP_FILE_NODE *FileNode, PCVOID Buffer, ULONG Size, ULONG StreamInfoChangeNumber); -static VOID FspFileNodeInvalidateStreamInfo(FSP_FILE_NODE *FileNode); -VOID FspFileNodeNotifyChange(FSP_FILE_NODE *FileNode, - ULONG Filter, ULONG Action); +VOID FspFileNodeInvalidateStreamInfo(FSP_FILE_NODE *FileNode); +VOID FspFileNodeNotifyChange(FSP_FILE_NODE *FileNode, ULONG Filter, ULONG Action, + BOOLEAN InvalidateCaches); NTSTATUS FspFileNodeProcessLockIrp(FSP_FILE_NODE *FileNode, PIRP Irp); static NTSTATUS FspFileNodeCompleteLockIrp(PVOID Context, PIRP Irp); NTSTATUS FspFileDescCreate(FSP_FILE_DESC **PFileDesc); @@ -1746,7 +1746,7 @@ BOOLEAN FspFileNodeTrySetStreamInfo(FSP_FILE_NODE *FileNode, PCVOID Buffer, ULON return TRUE; } -static VOID FspFileNodeInvalidateStreamInfo(FSP_FILE_NODE *FileNode) +VOID FspFileNodeInvalidateStreamInfo(FSP_FILE_NODE *FileNode) { // !PAGED_CODE(); @@ -1767,8 +1767,8 @@ static VOID FspFileNodeInvalidateStreamInfo(FSP_FILE_NODE *FileNode) FspMetaCacheInvalidateItem(FsvolDeviceExtension->StreamInfoCache, StreamInfo); } -VOID FspFileNodeNotifyChange(FSP_FILE_NODE *FileNode, - ULONG Filter, ULONG Action) +VOID FspFileNodeNotifyChange(FSP_FILE_NODE *FileNode, ULONG Filter, ULONG Action, + BOOLEAN InvalidateCaches) { /* FileNode must be acquired (exclusive or shared) Main */ @@ -1778,19 +1778,6 @@ VOID FspFileNodeNotifyChange(FSP_FILE_NODE *FileNode, FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject); UNICODE_STRING Parent, Suffix; - FspFileNameSuffix(&FileNode->FileName, &Parent, &Suffix); - - switch (Action) - { - case FILE_ACTION_ADDED: - case FILE_ACTION_REMOVED: - case FILE_ACTION_RENAMED_OLD_NAME: - case FILE_ACTION_RENAMED_NEW_NAME: - FspFsvolDeviceInvalidateVolumeInfo(FsvolDeviceObject); - FspFileNodeInvalidateDirInfoByName(FsvolDeviceObject, &Parent); - break; - } - if (0 != FileNode->MainFileNode) { if (FlagOn(Filter, FILE_NOTIFY_CHANGE_DIR_NAME | FILE_NOTIFY_CHANGE_FILE_NAME)) @@ -1804,25 +1791,40 @@ VOID FspFileNodeNotifyChange(FSP_FILE_NODE *FileNode, { case FILE_ACTION_ADDED: Action = FILE_ACTION_ADDED_STREAM; - FspFileNodeInvalidateStreamInfo(FileNode); break; case FILE_ACTION_REMOVED: Action = FILE_ACTION_REMOVED_STREAM; - FspFileNodeInvalidateStreamInfo(FileNode); break; case FILE_ACTION_MODIFIED: Action = FILE_ACTION_MODIFIED_STREAM; - //FspFileNodeInvalidateStreamInfo(FileNode); break; } } if (0 != Filter) + { + FspFileNameSuffix(&FileNode->FileName, &Parent, &Suffix); + + if (InvalidateCaches) + { + FspFsvolDeviceInvalidateVolumeInfo(FsvolDeviceObject); + if (0 == FileNode->MainFileNode) + { + if (sizeof(WCHAR) == FileNode->FileName.Length && L'\\' == FileNode->FileName.Buffer[0]) + ; /* root does not have a parent */ + else + FspFileNodeInvalidateDirInfoByName(FsvolDeviceObject, &Parent); + } + else + FspFileNodeInvalidateStreamInfo(FileNode); + } + FspNotifyReportChange( FsvolDeviceExtension->NotifySync, &FsvolDeviceExtension->NotifyList, &FileNode->FileName, (USHORT)((PUINT8)Suffix.Buffer - (PUINT8)FileNode->FileName.Buffer), 0, Filter, Action); + } } NTSTATUS FspFileNodeProcessLockIrp(FSP_FILE_NODE *FileNode, PIRP Irp) diff --git a/src/sys/fileinfo.c b/src/sys/fileinfo.c index e1115fa1..0c453af5 100644 --- a/src/sys/fileinfo.c +++ b/src/sys/fileinfo.c @@ -906,7 +906,7 @@ static NTSTATUS FspFsvolSetAllocationInformation(PFILE_OBJECT FileObject, /* mark the file object as modified */ SetFlag(FileObject->Flags, FO_FILE_MODIFIED); - FspFileNodeNotifyChange(FileNode, FILE_NOTIFY_CHANGE_SIZE, FILE_ACTION_MODIFIED); + FspFileNodeNotifyChange(FileNode, FILE_NOTIFY_CHANGE_SIZE, FILE_ACTION_MODIFIED, FALSE); } return STATUS_SUCCESS; @@ -997,7 +997,7 @@ static NTSTATUS FspFsvolSetBasicInformation(PFILE_OBJECT FileObject, FileDesc->DidSetChangeTime = TRUE; FileDesc->DidSetMetadata = TRUE; - FspFileNodeNotifyChange(FileNode, NotifyFilter, FILE_ACTION_MODIFIED); + FspFileNodeNotifyChange(FileNode, NotifyFilter, FILE_ACTION_MODIFIED, FALSE); } return STATUS_SUCCESS; @@ -1047,7 +1047,7 @@ static NTSTATUS FspFsvolSetEndOfFileInformation(PFILE_OBJECT FileObject, /* mark the file object as modified -- FastFat does this only for Allocation though! */ SetFlag(FileObject->Flags, FO_FILE_MODIFIED); - FspFileNodeNotifyChange(FileNode, FILE_NOTIFY_CHANGE_SIZE, FILE_ACTION_MODIFIED); + FspFileNodeNotifyChange(FileNode, FILE_NOTIFY_CHANGE_SIZE, FILE_ACTION_MODIFIED, FALSE); } return STATUS_SUCCESS; @@ -1394,7 +1394,8 @@ static NTSTATUS FspFsvolSetRenameInformationSuccess( /* fastfat has some really arcane rules on rename notifications; simplify! */ FspFileNodeNotifyChange(FileNode, FileNode->IsDirectory ? FILE_NOTIFY_CHANGE_DIR_NAME : FILE_NOTIFY_CHANGE_FILE_NAME, - FILE_ACTION_RENAMED_OLD_NAME); + FILE_ACTION_RENAMED_OLD_NAME, + TRUE); NewFileName.Length = NewFileName.MaximumLength = Request->Req.SetInformation.Info.Rename.NewFileName.Size - sizeof(WCHAR); @@ -1405,7 +1406,8 @@ static NTSTATUS FspFsvolSetRenameInformationSuccess( /* fastfat has some really arcane rules on rename notifications; simplify! */ FspFileNodeNotifyChange(FileNode, FileNode->IsDirectory ? FILE_NOTIFY_CHANGE_DIR_NAME : FILE_NOTIFY_CHANGE_FILE_NAME, - FILE_ACTION_RENAMED_NEW_NAME); + FILE_ACTION_RENAMED_NEW_NAME, + TRUE); FspIopRequestContext(Request, RequestFileNode) = 0; FspIopRequestContext(Request, RequestDeviceObject) = 0; diff --git a/src/sys/write.c b/src/sys/write.c index fa79fc28..57dac9d8 100644 --- a/src/sys/write.c +++ b/src/sys/write.c @@ -487,7 +487,7 @@ NTSTATUS FspFsvolWriteComplete( FspFileNodeSetFileInfo(FileNode, FileObject, &Response->Rsp.Write.FileInfo, TRUE); if (OriginalFileSize != Response->Rsp.Write.FileInfo.FileSize) - FspFileNodeNotifyChange(FileNode, FILE_NOTIFY_CHANGE_SIZE, FILE_ACTION_MODIFIED); + FspFileNodeNotifyChange(FileNode, FILE_NOTIFY_CHANGE_SIZE, FILE_ACTION_MODIFIED, FALSE); /* update the current file offset if synchronous I/O (and not paging I/O) */ if (SynchronousIo && !PagingIo)