mirror of
https://github.com/winfsp/winfsp.git
synced 2025-06-08 04:52:10 -05:00
tst: memfs: reference counting and descendant enumeration improvements
This commit is contained in:
parent
bbb51b4971
commit
c37444b0ae
@ -254,6 +254,19 @@ VOID MemfsFileNodeDelete(MEMFS_FILE_NODE *FileNode)
|
|||||||
free(FileNode);
|
free(FileNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline
|
||||||
|
VOID MemfsFileNodeReference(MEMFS_FILE_NODE *FileNode)
|
||||||
|
{
|
||||||
|
FileNode->RefCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline
|
||||||
|
VOID MemfsFileNodeDereference(MEMFS_FILE_NODE *FileNode)
|
||||||
|
{
|
||||||
|
if (0 == --FileNode->RefCount)
|
||||||
|
MemfsFileNodeDelete(FileNode);
|
||||||
|
}
|
||||||
|
|
||||||
static inline
|
static inline
|
||||||
VOID MemfsFileNodeGetFileInfo(MEMFS_FILE_NODE *FileNode, FSP_FSCTL_FILE_INFO *FileInfo)
|
VOID MemfsFileNodeGetFileInfo(MEMFS_FILE_NODE *FileNode, FSP_FSCTL_FILE_INFO *FileInfo)
|
||||||
{
|
{
|
||||||
@ -379,7 +392,7 @@ NTSTATUS MemfsFileNodeMapInsert(MEMFS_FILE_NODE_MAP *FileNodeMap, MEMFS_FILE_NOD
|
|||||||
{
|
{
|
||||||
*PInserted = FileNodeMap->insert(MEMFS_FILE_NODE_MAP::value_type(FileNode->FileName, FileNode)).second;
|
*PInserted = FileNodeMap->insert(MEMFS_FILE_NODE_MAP::value_type(FileNode->FileName, FileNode)).second;
|
||||||
if (*PInserted)
|
if (*PInserted)
|
||||||
FileNode->RefCount++;
|
MemfsFileNodeReference(FileNode);
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
catch (...)
|
catch (...)
|
||||||
@ -392,7 +405,7 @@ static inline
|
|||||||
VOID MemfsFileNodeMapRemove(MEMFS_FILE_NODE_MAP *FileNodeMap, MEMFS_FILE_NODE *FileNode)
|
VOID MemfsFileNodeMapRemove(MEMFS_FILE_NODE_MAP *FileNodeMap, MEMFS_FILE_NODE *FileNode)
|
||||||
{
|
{
|
||||||
if (FileNodeMap->erase(FileNode->FileName))
|
if (FileNodeMap->erase(FileNode->FileName))
|
||||||
--FileNode->RefCount;
|
MemfsFileNodeDereference(FileNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline
|
static inline
|
||||||
@ -504,6 +517,53 @@ BOOLEAN MemfsFileNodeMapEnumerateDescendants(MEMFS_FILE_NODE_MAP *FileNodeMap, M
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct _MEMFS_FILE_NODE_MAP_ENUM_CONTEXT
|
||||||
|
{
|
||||||
|
BOOLEAN Reference;
|
||||||
|
MEMFS_FILE_NODE **FileNodes;
|
||||||
|
ULONG Capacity, Count;
|
||||||
|
} MEMFS_FILE_NODE_MAP_ENUM_CONTEXT;
|
||||||
|
|
||||||
|
static inline
|
||||||
|
BOOLEAN MemfsFileNodeMapEnumerateFn(MEMFS_FILE_NODE *FileNode, PVOID Context0)
|
||||||
|
{
|
||||||
|
MEMFS_FILE_NODE_MAP_ENUM_CONTEXT *Context = (MEMFS_FILE_NODE_MAP_ENUM_CONTEXT *)Context0;
|
||||||
|
|
||||||
|
if (Context->Capacity <= Context->Count)
|
||||||
|
{
|
||||||
|
ULONG Capacity = 0 != Context->Capacity ? Context->Capacity * 2 : 16;
|
||||||
|
PVOID P = realloc(Context->FileNodes, Capacity * sizeof Context->FileNodes[0]);
|
||||||
|
if (0 == P)
|
||||||
|
{
|
||||||
|
FspDebugLog(__FUNCTION__ ": cannot allocate memory; aborting\n");
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
Context->FileNodes = (MEMFS_FILE_NODE **)P;
|
||||||
|
Context->Capacity = Capacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
Context->FileNodes[Context->Count++] = FileNode;
|
||||||
|
if (Context->Reference)
|
||||||
|
MemfsFileNodeReference(FileNode);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline
|
||||||
|
VOID MemfsFileNodeMapEnumerateFree(MEMFS_FILE_NODE_MAP_ENUM_CONTEXT *Context)
|
||||||
|
{
|
||||||
|
if (Context->Reference)
|
||||||
|
{
|
||||||
|
for (ULONG Index = 0; Context->Count > Index; Index++)
|
||||||
|
{
|
||||||
|
MEMFS_FILE_NODE *FileNode = Context->FileNodes[Index];
|
||||||
|
MemfsFileNodeDereference(FileNode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(Context->FileNodes);
|
||||||
|
}
|
||||||
|
|
||||||
typedef std::unordered_map<UINT64, std::wstring> MEMFS_DIR_DESC;
|
typedef std::unordered_map<UINT64, std::wstring> MEMFS_DIR_DESC;
|
||||||
|
|
||||||
static inline
|
static inline
|
||||||
@ -776,7 +836,7 @@ static NTSTATUS Create(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
FileNode->RefCount++;
|
MemfsFileNodeReference(FileNode);
|
||||||
*PFileNode = FileNode;
|
*PFileNode = FileNode;
|
||||||
MemfsFileNodeGetFileInfo(FileNode, FileInfo);
|
MemfsFileNodeGetFileInfo(FileNode, FileInfo);
|
||||||
|
|
||||||
@ -836,7 +896,7 @@ static NTSTATUS Open(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
(GrantedAccess & (FILE_WRITE_DATA | FILE_APPEND_DATA)))
|
(GrantedAccess & (FILE_WRITE_DATA | FILE_APPEND_DATA)))
|
||||||
FileNode->FileInfo.FileAttributes |= FILE_ATTRIBUTE_ARCHIVE;
|
FileNode->FileInfo.FileAttributes |= FILE_ATTRIBUTE_ARCHIVE;
|
||||||
|
|
||||||
FileNode->RefCount++;
|
MemfsFileNodeReference(FileNode);
|
||||||
*PFileNode = FileNode;
|
*PFileNode = FileNode;
|
||||||
MemfsFileNodeGetFileInfo(FileNode, FileInfo);
|
MemfsFileNodeGetFileInfo(FileNode, FileInfo);
|
||||||
|
|
||||||
@ -883,23 +943,6 @@ static NTSTATUS Overwrite(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(MEMFS_NAMED_STREAMS)
|
|
||||||
typedef struct _MEMFS_CLEANUP_CONTEXT
|
|
||||||
{
|
|
||||||
MEMFS_FILE_NODE **FileNodes;
|
|
||||||
ULONG Count;
|
|
||||||
} MEMFS_CLEANUP_CONTEXT;
|
|
||||||
|
|
||||||
static BOOLEAN CleanupEnumFn(MEMFS_FILE_NODE *FileNode, PVOID Context0)
|
|
||||||
{
|
|
||||||
MEMFS_CLEANUP_CONTEXT *Context = (MEMFS_CLEANUP_CONTEXT *)Context0;
|
|
||||||
|
|
||||||
Context->FileNodes[Context->Count++] = FileNode;
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static VOID Cleanup(FSP_FILE_SYSTEM *FileSystem,
|
static VOID Cleanup(FSP_FILE_SYSTEM *FileSystem,
|
||||||
PVOID FileNode0, PWSTR FileName, BOOLEAN Delete)
|
PVOID FileNode0, PWSTR FileName, BOOLEAN Delete)
|
||||||
{
|
{
|
||||||
@ -911,17 +954,14 @@ static VOID Cleanup(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
if (Delete && !MemfsFileNodeMapHasChild(Memfs->FileNodeMap, FileNode))
|
if (Delete && !MemfsFileNodeMapHasChild(Memfs->FileNodeMap, FileNode))
|
||||||
{
|
{
|
||||||
#if defined(MEMFS_NAMED_STREAMS)
|
#if defined(MEMFS_NAMED_STREAMS)
|
||||||
MEMFS_CLEANUP_CONTEXT Context = { 0 };
|
MEMFS_FILE_NODE_MAP_ENUM_CONTEXT Context = { FALSE };
|
||||||
ULONG Index;
|
ULONG Index;
|
||||||
|
|
||||||
Context.FileNodes = (MEMFS_FILE_NODE **)malloc(Memfs->MaxFileNodes * sizeof Context.FileNodes[0]);
|
MemfsFileNodeMapEnumerateNamedStreams(Memfs->FileNodeMap, FileNode,
|
||||||
if (0 != Context.FileNodes)
|
MemfsFileNodeMapEnumerateFn, &Context);
|
||||||
{
|
for (Index = 0; Context.Count > Index; Index++)
|
||||||
MemfsFileNodeMapEnumerateNamedStreams(Memfs->FileNodeMap, FileNode, CleanupEnumFn, &Context);
|
MemfsFileNodeMapRemove(Memfs->FileNodeMap, Context.FileNodes[Index]);
|
||||||
for (Index = 0; Context.Count > Index; Index++)
|
MemfsFileNodeMapEnumerateFree(&Context);
|
||||||
MemfsFileNodeMapRemove(Memfs->FileNodeMap, Context.FileNodes[Index]);
|
|
||||||
free(Context.FileNodes);
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
MemfsFileNodeMapRemove(Memfs->FileNodeMap, FileNode);
|
MemfsFileNodeMapRemove(Memfs->FileNodeMap, FileNode);
|
||||||
@ -936,8 +976,7 @@ static VOID Close(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
MEMFS_DIR_DESC *DirDesc = (MEMFS_DIR_DESC *)(UINT_PTR)
|
MEMFS_DIR_DESC *DirDesc = (MEMFS_DIR_DESC *)(UINT_PTR)
|
||||||
FspFileSystemGetOperationContext()->Request->Req.Close.UserContext2;
|
FspFileSystemGetOperationContext()->Request->Req.Close.UserContext2;
|
||||||
|
|
||||||
if (0 == --FileNode->RefCount)
|
MemfsFileNodeDereference(FileNode);
|
||||||
MemfsFileNodeDelete(FileNode);
|
|
||||||
|
|
||||||
if (0 != DirDesc)
|
if (0 != DirDesc)
|
||||||
MemfsDirDescDelete(DirDesc);
|
MemfsDirDescDelete(DirDesc);
|
||||||
@ -1126,22 +1165,6 @@ static NTSTATUS CanDelete(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct _MEMFS_RENAME_CONTEXT
|
|
||||||
{
|
|
||||||
MEMFS_FILE_NODE **FileNodes;
|
|
||||||
ULONG Count;
|
|
||||||
} MEMFS_RENAME_CONTEXT;
|
|
||||||
|
|
||||||
static BOOLEAN RenameEnumFn(MEMFS_FILE_NODE *FileNode, PVOID Context0)
|
|
||||||
{
|
|
||||||
MEMFS_RENAME_CONTEXT *Context = (MEMFS_RENAME_CONTEXT *)Context0;
|
|
||||||
|
|
||||||
Context->FileNodes[Context->Count++] = FileNode;
|
|
||||||
FileNode->RefCount++;
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static NTSTATUS Rename(FSP_FILE_SYSTEM *FileSystem,
|
static NTSTATUS Rename(FSP_FILE_SYSTEM *FileSystem,
|
||||||
PVOID FileNode0,
|
PVOID FileNode0,
|
||||||
PWSTR FileName, PWSTR NewFileName, BOOLEAN ReplaceIfExists)
|
PWSTR FileName, PWSTR NewFileName, BOOLEAN ReplaceIfExists)
|
||||||
@ -1149,7 +1172,7 @@ static NTSTATUS Rename(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
MEMFS *Memfs = (MEMFS *)FileSystem->UserContext;
|
MEMFS *Memfs = (MEMFS *)FileSystem->UserContext;
|
||||||
MEMFS_FILE_NODE *FileNode = (MEMFS_FILE_NODE *)FileNode0;
|
MEMFS_FILE_NODE *FileNode = (MEMFS_FILE_NODE *)FileNode0;
|
||||||
MEMFS_FILE_NODE *NewFileNode, *DescendantFileNode;
|
MEMFS_FILE_NODE *NewFileNode, *DescendantFileNode;
|
||||||
MEMFS_RENAME_CONTEXT Context = { 0 };
|
MEMFS_FILE_NODE_MAP_ENUM_CONTEXT Context = { TRUE };
|
||||||
ULONG Index, FileNameLen, NewFileNameLen;
|
ULONG Index, FileNameLen, NewFileNameLen;
|
||||||
BOOLEAN Inserted;
|
BOOLEAN Inserted;
|
||||||
NTSTATUS Result;
|
NTSTATUS Result;
|
||||||
@ -1170,14 +1193,8 @@ static NTSTATUS Rename(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Context.FileNodes = (MEMFS_FILE_NODE **)malloc(Memfs->MaxFileNodes * sizeof Context.FileNodes[0]);
|
MemfsFileNodeMapEnumerateDescendants(Memfs->FileNodeMap, FileNode,
|
||||||
if (0 == Context.FileNodes)
|
MemfsFileNodeMapEnumerateFn, &Context);
|
||||||
{
|
|
||||||
Result = STATUS_INSUFFICIENT_RESOURCES;
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
MemfsFileNodeMapEnumerateDescendants(Memfs->FileNodeMap, FileNode, RenameEnumFn, &Context);
|
|
||||||
|
|
||||||
FileNameLen = (ULONG)wcslen(FileNode->FileName);
|
FileNameLen = (ULONG)wcslen(FileNode->FileName);
|
||||||
NewFileNameLen = (ULONG)wcslen(NewFileName);
|
NewFileNameLen = (ULONG)wcslen(NewFileName);
|
||||||
@ -1193,10 +1210,9 @@ static NTSTATUS Rename(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
|
|
||||||
if (0 != NewFileNode)
|
if (0 != NewFileNode)
|
||||||
{
|
{
|
||||||
NewFileNode->RefCount++;
|
MemfsFileNodeReference(NewFileNode);
|
||||||
MemfsFileNodeMapRemove(Memfs->FileNodeMap, NewFileNode);
|
MemfsFileNodeMapRemove(Memfs->FileNodeMap, NewFileNode);
|
||||||
if (0 == --NewFileNode->RefCount)
|
MemfsFileNodeDereference(NewFileNode);
|
||||||
MemfsFileNodeDelete(NewFileNode);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Index = 0; Context.Count > Index; Index++)
|
for (Index = 0; Context.Count > Index; Index++)
|
||||||
@ -1219,12 +1235,7 @@ static NTSTATUS Rename(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
Result = STATUS_SUCCESS;
|
Result = STATUS_SUCCESS;
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
for (Index = 0; Context.Count > Index; Index++)
|
MemfsFileNodeMapEnumerateFree(&Context);
|
||||||
{
|
|
||||||
DescendantFileNode = Context.FileNodes[Index];
|
|
||||||
DescendantFileNode->RefCount--;
|
|
||||||
}
|
|
||||||
free(Context.FileNodes);
|
|
||||||
|
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user