From 0f63dddb3211e6bae28462df7e1b0a5818e59f6f Mon Sep 17 00:00:00 2001 From: Bill Zissimopoulos Date: Wed, 8 Jun 2016 20:43:52 -0700 Subject: [PATCH] dll: FspFileSystemOpEnter, FspFileSystemOpLeave --- inc/winfsp/winfsp.h | 17 +++++++++ src/dll/fs.c | 5 +++ src/dll/fsop.c | 86 +++++++++++++++++++++++++++++++++++++++++++++ src/dll/fuse/fuse.c | 16 +++++++-- tst/memfs/memfs.cpp | 26 +++----------- 5 files changed, 125 insertions(+), 25 deletions(-) diff --git a/inc/winfsp/winfsp.h b/inc/winfsp/winfsp.h index e775037c..6351dddd 100644 --- a/inc/winfsp/winfsp.h +++ b/inc/winfsp/winfsp.h @@ -577,6 +577,11 @@ typedef struct _FSP_FILE_SYSTEM_INTERFACE PWSTR Pattern, PULONG PBytesTransferred); } FSP_FILE_SYSTEM_INTERFACE; +typedef enum +{ + FSP_FILE_SYSTEM_OPERATION_GUARD_STRATEGY_FINE = 0, + FSP_FILE_SYSTEM_OPERATION_GUARD_STRATEGY_COARSE, +} FSP_FILE_SYSTEM_OPERATION_GUARD_STRATEGY; typedef struct _FSP_FILE_SYSTEM { UINT16 Version; @@ -592,6 +597,8 @@ typedef struct _FSP_FILE_SYSTEM PWSTR MountPoint; LIST_ENTRY MountEntry; UINT32 DebugLog; + FSP_FILE_SYSTEM_OPERATION_GUARD_STRATEGY OpGuardStrategy; + SRWLOCK OpGuardLock; } FSP_FILE_SYSTEM; /** * Create a file system object. @@ -716,6 +723,12 @@ VOID FspFileSystemSetOperationGuard(FSP_FILE_SYSTEM *FileSystem, FileSystem->LeaveOperation = LeaveOperation; } static inline +VOID FspFileSystemSetOperationGuardStrategy(FSP_FILE_SYSTEM *FileSystem, + FSP_FILE_SYSTEM_OPERATION_GUARD_STRATEGY GuardStrategy) +{ + FileSystem->OpGuardStrategy = GuardStrategy; +} +static inline VOID FspFileSystemSetOperation(FSP_FILE_SYSTEM *FileSystem, ULONG Index, FSP_FILE_SYSTEM_OPERATION *Operation) @@ -748,6 +761,10 @@ VOID FspFileSystemSetDebugLog(FSP_FILE_SYSTEM *FileSystem, /* * Operations */ +FSP_API VOID FspFileSystemOpEnter(FSP_FILE_SYSTEM *FileSystem, + FSP_FSCTL_TRANSACT_REQ *Request, FSP_FSCTL_TRANSACT_RSP *Response); +FSP_API VOID FspFileSystemOpLeave(FSP_FILE_SYSTEM *FileSystem, + FSP_FSCTL_TRANSACT_REQ *Request, FSP_FSCTL_TRANSACT_RSP *Response); FSP_API NTSTATUS FspFileSystemOpCreate(FSP_FILE_SYSTEM *FileSystem, FSP_FSCTL_TRANSACT_REQ *Request, FSP_FSCTL_TRANSACT_RSP *Response); FSP_API NTSTATUS FspFileSystemOpOverwrite(FSP_FILE_SYSTEM *FileSystem, diff --git a/src/dll/fs.c b/src/dll/fs.c index c3ffe8a9..cffa2dbe 100644 --- a/src/dll/fs.c +++ b/src/dll/fs.c @@ -125,6 +125,11 @@ FSP_API NTSTATUS FspFileSystemCreate(PWSTR DevicePath, FileSystem->Operations[FspFsctlTransactSetSecurityKind] = FspFileSystemOpSetSecurity; FileSystem->Interface = Interface; + FileSystem->OpGuardStrategy = FSP_FILE_SYSTEM_OPERATION_GUARD_STRATEGY_FINE; + InitializeSRWLock(&FileSystem->OpGuardLock); + FileSystem->EnterOperation = FspFileSystemOpEnter; + FileSystem->LeaveOperation = FspFileSystemOpLeave; + *PFileSystem = FileSystem; return STATUS_SUCCESS; diff --git a/src/dll/fsop.c b/src/dll/fsop.c index 4e34a3f6..74ac0a5c 100644 --- a/src/dll/fsop.c +++ b/src/dll/fsop.c @@ -17,6 +17,92 @@ #include +/* + * The FspFileSystemOpEnter/FspFileSystemOpLeave functions guard against + * concurrent accesses. Two concurrency models are provided: + * + * 1. A fine-grained concurrency model where file system NAMESPACE accesses + * are guarded using an exclusive-shared (read-write) lock. File I/O is not + * guarded and concurrent reads/writes/etc. are possible. [Note that the FSD + * will still apply an exclusive-shared lock PER INDIVIDUAL FILE, but it will + * not limit I/O operations for different files.] + * + * The fine-grained concurrency model applies the exclusive-shared lock as + * follows: + * - EXCL: SetVolumeLabel, Create, Cleanup(Delete), SetInformation(Rename) + * - SHRD: GetVolumeInfo, Open, SetInformation(Disposition), ReadDirectory + * - NONE: all other operations + * + * 2. A coarse-grained concurrency model where all file system accesses are + * guarded by a mutually exclusive lock. + */ + +FSP_API VOID FspFileSystemOpEnter(FSP_FILE_SYSTEM *FileSystem, + FSP_FSCTL_TRANSACT_REQ *Request, FSP_FSCTL_TRANSACT_RSP *Response) +{ + switch (FileSystem->OpGuardStrategy) + { + case FSP_FILE_SYSTEM_OPERATION_GUARD_STRATEGY_FINE: + if ((FspFsctlTransactCreateKind == Request->Kind && + FILE_OPEN != ((Request->Req.Create.CreateOptions >> 24) & 0xff)) || + (FspFsctlTransactCleanupKind == Request->Kind && + Request->Req.Cleanup.Delete) || + (FspFsctlTransactSetInformationKind == Request->Kind && + 10/*FileRenameInformation*/ == Request->Req.SetInformation.FileInformationClass) || + FspFsctlTransactSetVolumeInformationKind == Request->Kind) + { + AcquireSRWLockExclusive(&FileSystem->OpGuardLock); + } + else + if (FspFsctlTransactCreateKind == Request->Kind || + (FspFsctlTransactSetInformationKind == Request->Kind && + 13/*FileDispositionInformation*/ == Request->Req.SetInformation.FileInformationClass) || + FspFsctlTransactQueryDirectoryKind == Request->Kind || + FspFsctlTransactQueryVolumeInformationKind == Request->Kind) + { + AcquireSRWLockShared(&FileSystem->OpGuardLock); + } + break; + + case FSP_FILE_SYSTEM_OPERATION_GUARD_STRATEGY_COARSE: + AcquireSRWLockExclusive(&FileSystem->OpGuardLock); + break; + } +} + +FSP_API VOID FspFileSystemOpLeave(FSP_FILE_SYSTEM *FileSystem, + FSP_FSCTL_TRANSACT_REQ *Request, FSP_FSCTL_TRANSACT_RSP *Response) +{ + switch (FileSystem->OpGuardStrategy) + { + case FSP_FILE_SYSTEM_OPERATION_GUARD_STRATEGY_FINE: + if ((FspFsctlTransactCreateKind == Request->Kind && + FILE_OPEN != ((Request->Req.Create.CreateOptions >> 24) & 0xff)) || + (FspFsctlTransactCleanupKind == Request->Kind && + Request->Req.Cleanup.Delete) || + (FspFsctlTransactSetInformationKind == Request->Kind && + 10/*FileRenameInformation*/ == Request->Req.SetInformation.FileInformationClass) || + FspFsctlTransactSetVolumeInformationKind == Request->Kind) + { + ReleaseSRWLockExclusive(&FileSystem->OpGuardLock); + } + else + if (FspFsctlTransactCreateKind == Request->Kind || + (FspFsctlTransactSetInformationKind == Request->Kind && + 13/*FileDispositionInformation*/ == Request->Req.SetInformation.FileInformationClass) || + FspFsctlTransactQueryDirectoryKind == Request->Kind || + FspFsctlTransactQueryVolumeInformationKind == Request->Kind) + { + ReleaseSRWLockShared(&FileSystem->OpGuardLock); + } + break; + + case FSP_FILE_SYSTEM_OPERATION_GUARD_STRATEGY_COARSE: + ReleaseSRWLockExclusive(&FileSystem->OpGuardLock); + break; + } +} + static inline NTSTATUS FspFileSystemCreateCheck(FSP_FILE_SYSTEM *FileSystem, FSP_FSCTL_TRANSACT_REQ *Request, diff --git a/src/dll/fuse/fuse.c b/src/dll/fuse/fuse.c index 6e5dcf20..c38c8e9a 100644 --- a/src/dll/fuse/fuse.c +++ b/src/dll/fuse/fuse.c @@ -587,12 +587,14 @@ FSP_FUSE_API void fsp_fuse_destroy(struct fsp_fuse_env *env, MemFree(f); } -FSP_FUSE_API int fsp_fuse_loop(struct fsp_fuse_env *env, - struct fuse *f) +static int fsp_fuse_loop_internal(struct fsp_fuse_env *env, + struct fuse *f, FSP_FILE_SYSTEM_OPERATION_GUARD_STRATEGY GuardStrategy) { NTSTATUS Result; ULONG ExitCode; + FspFileSystemSetOperationGuardStrategy(f->FileSystem, GuardStrategy); + Result = FspServiceLoop(f->Service); ExitCode = FspServiceGetExitCode(f->Service); @@ -612,10 +614,18 @@ fail: return -1; } +FSP_FUSE_API int fsp_fuse_loop(struct fsp_fuse_env *env, + struct fuse *f) +{ + return fsp_fuse_loop_internal(env, f, + FSP_FILE_SYSTEM_OPERATION_GUARD_STRATEGY_COARSE); +} + FSP_FUSE_API int fsp_fuse_loop_mt(struct fsp_fuse_env *env, struct fuse *f) { - return fsp_fuse_loop(env, f); + return fsp_fuse_loop_internal(env, f, + FSP_FILE_SYSTEM_OPERATION_GUARD_STRATEGY_FINE); } FSP_FUSE_API void fsp_fuse_exit(struct fsp_fuse_env *env, diff --git a/tst/memfs/memfs.cpp b/tst/memfs/memfs.cpp index 0e7cdd9f..2de91bf7 100644 --- a/tst/memfs/memfs.cpp +++ b/tst/memfs/memfs.cpp @@ -79,7 +79,6 @@ typedef struct _MEMFS ULONG MaxFileSize; UINT16 VolumeLabelLength; WCHAR VolumeLabel[32]; - CRITICAL_SECTION Lock; } MEMFS; static inline @@ -962,20 +961,6 @@ static FSP_FILE_SYSTEM_INTERFACE MemfsInterface = ReadDirectory, }; -static VOID MemfsEnterOperation(FSP_FILE_SYSTEM *FileSystem, - FSP_FSCTL_TRANSACT_REQ *Request, FSP_FSCTL_TRANSACT_RSP *Response) -{ - MEMFS *Memfs = (MEMFS *)FileSystem->UserContext; - EnterCriticalSection(&Memfs->Lock); -} - -static VOID MemfsLeaveOperation(FSP_FILE_SYSTEM *FileSystem, - FSP_FSCTL_TRANSACT_REQ *Request, FSP_FSCTL_TRANSACT_RSP *Response) -{ - MEMFS *Memfs = (MEMFS *)FileSystem->UserContext; - LeaveCriticalSection(&Memfs->Lock); -} - NTSTATUS MemfsCreate( ULONG Flags, ULONG FileInfoTimeout, @@ -1050,11 +1035,10 @@ NTSTATUS MemfsCreate( Memfs->VolumeLabelLength = sizeof L"MEMFS" - sizeof(WCHAR); memcpy(Memfs->VolumeLabel, L"MEMFS", Memfs->VolumeLabelLength); - InitializeCriticalSection(&Memfs->Lock); - - FspFileSystemSetOperationGuard(Memfs->FileSystem, - MemfsEnterOperation, - MemfsLeaveOperation); +#if 0 + FspFileSystemSetOperationGuardStrategy(Memfs->FileSystem, + FSP_FILE_SYSTEM_OPERATION_GUARD_STRATEGY_COARSE); +#endif /* * Create root directory. @@ -1099,8 +1083,6 @@ NTSTATUS MemfsCreate( VOID MemfsDelete(MEMFS *Memfs) { - DeleteCriticalSection(&Memfs->Lock); - FspFileSystemDelete(Memfs->FileSystem); MemfsFileNodeMapDelete(Memfs->FileNodeMap);