first stab at time-based data coherency
This commit is contained in:
parent
13c3723191
commit
43424fc653
1 changed files with 284 additions and 59 deletions
|
|
@ -66,7 +66,7 @@ PRDBSS_DEVICE_OBJECT nfs41_dev;
|
||||||
#define NFS41_MM_POOLTAG ('nfs4')
|
#define NFS41_MM_POOLTAG ('nfs4')
|
||||||
|
|
||||||
KEVENT upcallEvent;
|
KEVENT upcallEvent;
|
||||||
FAST_MUTEX upcallLock, downcallLock;
|
FAST_MUTEX upcallLock, downcallLock, srvopenLock;
|
||||||
FAST_MUTEX xidLock;
|
FAST_MUTEX xidLock;
|
||||||
FAST_MUTEX openOwnerLock;
|
FAST_MUTEX openOwnerLock;
|
||||||
|
|
||||||
|
|
@ -317,7 +317,6 @@ typedef struct _NFS41_MOUNT_CONFIG {
|
||||||
BOOLEAN ReadOnly;
|
BOOLEAN ReadOnly;
|
||||||
BOOLEAN write_thru;
|
BOOLEAN write_thru;
|
||||||
BOOLEAN nocache;
|
BOOLEAN nocache;
|
||||||
BOOLEAN nocoherence;
|
|
||||||
WCHAR srv_buffer[SERVER_NAME_BUFFER_SIZE];
|
WCHAR srv_buffer[SERVER_NAME_BUFFER_SIZE];
|
||||||
UNICODE_STRING SrvName;
|
UNICODE_STRING SrvName;
|
||||||
WCHAR mntpt_buffer[MAX_PATH];
|
WCHAR mntpt_buffer[MAX_PATH];
|
||||||
|
|
@ -358,7 +357,6 @@ typedef struct _NFS41_V_NET_ROOT_EXTENSION {
|
||||||
BOOLEAN read_only;
|
BOOLEAN read_only;
|
||||||
BOOLEAN write_thru;
|
BOOLEAN write_thru;
|
||||||
BOOLEAN nocache;
|
BOOLEAN nocache;
|
||||||
BOOLEAN nocoherence;
|
|
||||||
#define STORE_MOUNT_SEC_CONTEXT
|
#define STORE_MOUNT_SEC_CONTEXT
|
||||||
#ifdef STORE_MOUNT_SEC_CONTEXT
|
#ifdef STORE_MOUNT_SEC_CONTEXT
|
||||||
SECURITY_CLIENT_CONTEXT mount_sec_ctx;
|
SECURITY_CLIENT_CONTEXT mount_sec_ctx;
|
||||||
|
|
@ -390,6 +388,7 @@ typedef struct _NFS41_FOBX {
|
||||||
PVOID acl;
|
PVOID acl;
|
||||||
DWORD acl_len;
|
DWORD acl_len;
|
||||||
LARGE_INTEGER time;
|
LARGE_INTEGER time;
|
||||||
|
DWORD deleg_type;
|
||||||
} NFS41_FOBX, *PNFS41_FOBX;
|
} NFS41_FOBX, *PNFS41_FOBX;
|
||||||
#define NFS41GetFobxExtension(pFobx) \
|
#define NFS41GetFobxExtension(pFobx) \
|
||||||
(((pFobx) == NULL) ? NULL : (PNFS41_FOBX)((pFobx)->Context))
|
(((pFobx) == NULL) ? NULL : (PNFS41_FOBX)((pFobx)->Context))
|
||||||
|
|
@ -409,12 +408,26 @@ typedef struct _NFS41_DEVICE_EXTENSION {
|
||||||
DWORD nfs41d_version;
|
DWORD nfs41d_version;
|
||||||
BYTE VolAttrs[VOL_ATTR_LEN];
|
BYTE VolAttrs[VOL_ATTR_LEN];
|
||||||
DWORD VolAttrsLen;
|
DWORD VolAttrsLen;
|
||||||
|
HANDLE openlistHandle;
|
||||||
} NFS41_DEVICE_EXTENSION, *PNFS41_DEVICE_EXTENSION;
|
} NFS41_DEVICE_EXTENSION, *PNFS41_DEVICE_EXTENSION;
|
||||||
|
|
||||||
#define NFS41GetDeviceExtension(RxContext,pExt) \
|
#define NFS41GetDeviceExtension(RxContext,pExt) \
|
||||||
PNFS41_DEVICE_EXTENSION pExt = (PNFS41_DEVICE_EXTENSION) \
|
PNFS41_DEVICE_EXTENSION pExt = (PNFS41_DEVICE_EXTENSION) \
|
||||||
((PBYTE)(RxContext->RxDeviceObject) + sizeof(RDBSS_DEVICE_OBJECT))
|
((PBYTE)(RxContext->RxDeviceObject) + sizeof(RDBSS_DEVICE_OBJECT))
|
||||||
|
|
||||||
|
typedef struct _nfs41_srvopen_list_entry {
|
||||||
|
LIST_ENTRY next;
|
||||||
|
PMRX_SRV_OPEN srv_open;
|
||||||
|
PNFS41_FOBX nfs41_fobx;
|
||||||
|
ULONGLONG ChangeTime;
|
||||||
|
BOOLEAN skip;
|
||||||
|
} nfs41_srvopen_list_entry;
|
||||||
|
|
||||||
|
typedef struct _nfs41_srvopen_list {
|
||||||
|
LIST_ENTRY head;
|
||||||
|
} nfs41_srvopen_list;
|
||||||
|
nfs41_srvopen_list *openlist = NULL;
|
||||||
|
|
||||||
typedef enum _NULMRX_STORAGE_TYPE_CODES {
|
typedef enum _NULMRX_STORAGE_TYPE_CODES {
|
||||||
NTC_NFS41_DEVICE_EXTENSION = (NODE_TYPE_CODE)0xFC00,
|
NTC_NFS41_DEVICE_EXTENSION = (NODE_TYPE_CODE)0xFC00,
|
||||||
} NFS41_STORAGE_TYPE_CODES;
|
} NFS41_STORAGE_TYPE_CODES;
|
||||||
|
|
@ -1670,6 +1683,7 @@ void unmarshal_nfs41_getattr(
|
||||||
unmarshal_nfs41_attrget(cur, cur->u.QueryFile.buf,
|
unmarshal_nfs41_attrget(cur, cur->u.QueryFile.buf,
|
||||||
&cur->u.QueryFile.buf_len, buf);
|
&cur->u.QueryFile.buf_len, buf);
|
||||||
RtlCopyMemory(&cur->u.QueryFile.ChangeTime, *buf, sizeof(LONGLONG));
|
RtlCopyMemory(&cur->u.QueryFile.ChangeTime, *buf, sizeof(LONGLONG));
|
||||||
|
if (cur->u.QueryFile.InfoClass == FileBasicInformation)
|
||||||
DbgP("[getattr] ChangeTime %llu\n", cur->u.QueryFile.ChangeTime);
|
DbgP("[getattr] ChangeTime %llu\n", cur->u.QueryFile.ChangeTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2530,7 +2544,6 @@ void nfs41_MountConfig_InitDefaults(
|
||||||
Config->ReadOnly = FALSE;
|
Config->ReadOnly = FALSE;
|
||||||
Config->write_thru = FALSE;
|
Config->write_thru = FALSE;
|
||||||
Config->nocache = FALSE;
|
Config->nocache = FALSE;
|
||||||
Config->nocoherence = FALSE;
|
|
||||||
Config->SrvName.Length = 0;
|
Config->SrvName.Length = 0;
|
||||||
Config->SrvName.MaximumLength = SERVER_NAME_BUFFER_SIZE;
|
Config->SrvName.MaximumLength = SERVER_NAME_BUFFER_SIZE;
|
||||||
Config->SrvName.Buffer = Config->srv_buffer;
|
Config->SrvName.Buffer = Config->srv_buffer;
|
||||||
|
|
@ -2624,10 +2637,6 @@ NTSTATUS nfs41_MountConfig_ParseOptions(
|
||||||
status = nfs41_MountConfig_ParseBoolean(Option, &usValue,
|
status = nfs41_MountConfig_ParseBoolean(Option, &usValue,
|
||||||
&Config->nocache);
|
&Config->nocache);
|
||||||
}
|
}
|
||||||
else if (wcsncmp(L"nocoherence", Name, NameLen) == 0) {
|
|
||||||
status = nfs41_MountConfig_ParseBoolean(Option, &usValue,
|
|
||||||
&Config->nocoherence);
|
|
||||||
}
|
|
||||||
else if (wcsncmp(L"rsize", Name, NameLen) == 0) {
|
else if (wcsncmp(L"rsize", Name, NameLen) == 0) {
|
||||||
status = nfs41_MountConfig_ParseDword(Option, &usValue,
|
status = nfs41_MountConfig_ParseDword(Option, &usValue,
|
||||||
&Config->ReadSize, MOUNT_CONFIG_RW_SIZE_MIN,
|
&Config->ReadSize, MOUNT_CONFIG_RW_SIZE_MIN,
|
||||||
|
|
@ -2830,7 +2839,6 @@ NTSTATUS nfs41_CreateVNetRoot(
|
||||||
pVNetRootContext->read_only = Config.ReadOnly;
|
pVNetRootContext->read_only = Config.ReadOnly;
|
||||||
pVNetRootContext->write_thru = Config.write_thru;
|
pVNetRootContext->write_thru = Config.write_thru;
|
||||||
pVNetRootContext->nocache = Config.nocache;
|
pVNetRootContext->nocache = Config.nocache;
|
||||||
pVNetRootContext->nocoherence = Config.nocoherence;
|
|
||||||
} else {
|
} else {
|
||||||
/* use the SRV_CALL name (without leading \) as the hostname */
|
/* use the SRV_CALL name (without leading \) as the hostname */
|
||||||
Config.SrvName.Buffer = pSrvCall->pSrvCallName->Buffer + 1;
|
Config.SrvName.Buffer = pSrvCall->pSrvCallName->Buffer + 1;
|
||||||
|
|
@ -3182,19 +3190,6 @@ BOOLEAN isDataAccess(
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOLEAN has_file_changed(
|
|
||||||
IN ULONGLONG new_changeattr,
|
|
||||||
IN PFILE_BASIC_INFORMATION new_binfo,
|
|
||||||
IN PNFS41_FCB nfs41_fcb)
|
|
||||||
{
|
|
||||||
if (new_changeattr != nfs41_fcb->changeattr && nfs41_fcb->changeattr)
|
|
||||||
return TRUE;
|
|
||||||
if (new_binfo->ChangeTime.QuadPart !=
|
|
||||||
nfs41_fcb->BasicInfo.ChangeTime.QuadPart)
|
|
||||||
return TRUE;
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
NTSTATUS map_open_errors(
|
NTSTATUS map_open_errors(
|
||||||
DWORD status,
|
DWORD status,
|
||||||
USHORT len)
|
USHORT len)
|
||||||
|
|
@ -3425,10 +3420,9 @@ NTSTATUS nfs41_Create(
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// we get attributes only for data access and file (not directories)
|
// we get attributes only for data access and file (not directories)
|
||||||
if (Fcb->OpenCount > 0)
|
if (Fcb->OpenCount == 0 ||
|
||||||
file_changed = has_file_changed(entry->u.Open.changeattr,
|
(Fcb->OpenCount > 0 &&
|
||||||
&entry->u.Open.binfo, nfs41_fcb);
|
nfs41_fcb->changeattr != entry->u.Open.changeattr)) {
|
||||||
if (Fcb->OpenCount == 0 || file_changed) {
|
|
||||||
print_basic_info(1, &entry->u.Open.binfo);
|
print_basic_info(1, &entry->u.Open.binfo);
|
||||||
print_std_info(1, &entry->u.Open.sinfo);
|
print_std_info(1, &entry->u.Open.sinfo);
|
||||||
RtlCopyMemory(&nfs41_fcb->BasicInfo, &entry->u.Open.binfo,
|
RtlCopyMemory(&nfs41_fcb->BasicInfo, &entry->u.Open.binfo,
|
||||||
|
|
@ -3466,44 +3460,52 @@ NTSTATUS nfs41_Create(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (file_changed && !nfs41_fcb->StandardInfo.Directory) {
|
if (Fcb->OpenCount > 0 &&
|
||||||
|
nfs41_fcb->changeattr != entry->u.Open.changeattr &&
|
||||||
|
!nfs41_fcb->StandardInfo.Directory) {
|
||||||
ULONG flag = DISABLE_CACHING;
|
ULONG flag = DISABLE_CACHING;
|
||||||
DbgP("file object %wZ changed\n", SrvOpen->pAlreadyPrefixedName);
|
DbgP("nfs41_Create: reopening (changed) file %wZ\n", SrvOpen->pAlreadyPrefixedName);
|
||||||
RxIndicateChangeOfBufferingStateForSrvOpen(
|
RxChangeBufferingState((PSRV_OPEN)SrvOpen, ULongToPtr(flag), 1);
|
||||||
SrvOpen->pVNetRoot->pNetRoot->pSrvCall,
|
|
||||||
SrvOpen, SrvOpen->Key, ULongToPtr(flag));
|
|
||||||
} else if (!file_changed && !nfs41_fcb->StandardInfo.Directory) {
|
} else if (!file_changed && !nfs41_fcb->StandardInfo.Directory) {
|
||||||
// windows does agressive write flushing (every 2s)
|
nfs41_fobx->deleg_type = entry->u.Open.deleg_type;
|
||||||
// thus we'll always turn on write buffering
|
DbgP("nfs41_Create: received delegation %d\n", entry->u.Open.deleg_type);
|
||||||
if ((!pVNetRootContext->nocoherence &&
|
if (!(params.CreateOptions & FILE_WRITE_THROUGH) &&
|
||||||
(entry->u.Open.deleg_type == 2 &&
|
|
||||||
!(params.CreateOptions & FILE_WRITE_THROUGH))) ||
|
|
||||||
(pVNetRootContext->nocoherence &&
|
|
||||||
((params.DesiredAccess & FILE_WRITE_DATA ||
|
|
||||||
params.DesiredAccess & FILE_APPEND_DATA) &&
|
|
||||||
!pVNetRootContext->write_thru &&
|
!pVNetRootContext->write_thru &&
|
||||||
!(params.CreateOptions & FILE_WRITE_THROUGH)))) {
|
(entry->u.Open.deleg_type == 2 ||
|
||||||
|
(params.DesiredAccess & (FILE_WRITE_DATA | FILE_APPEND_DATA)))) {
|
||||||
DbgP("nfs41_Create: enabling write buffering\n");
|
DbgP("nfs41_Create: enabling write buffering\n");
|
||||||
SrvOpen->BufferingFlags |=
|
SrvOpen->BufferingFlags |=
|
||||||
(FCB_STATE_WRITECACHING_ENABLED |
|
(FCB_STATE_WRITECACHING_ENABLED |
|
||||||
FCB_STATE_WRITEBUFFERING_ENABLED);
|
FCB_STATE_WRITEBUFFERING_ENABLED);
|
||||||
}
|
}
|
||||||
|
if (entry->u.Open.deleg_type >= 1 ||
|
||||||
// if we received read delegation, turn on read buffering
|
params.DesiredAccess & FILE_READ_DATA) {
|
||||||
if ((!pVNetRootContext->nocoherence &&
|
|
||||||
(entry->u.Open.deleg_type >= 1)) ||
|
|
||||||
(pVNetRootContext->nocoherence &&
|
|
||||||
(params.DesiredAccess & FILE_READ_DATA))) {
|
|
||||||
DbgP("nfs41_Create: enabling read buffering\n");
|
DbgP("nfs41_Create: enabling read buffering\n");
|
||||||
SrvOpen->BufferingFlags |=
|
SrvOpen->BufferingFlags |=
|
||||||
(FCB_STATE_READBUFFERING_ENABLED |
|
(FCB_STATE_READBUFFERING_ENABLED |
|
||||||
FCB_STATE_READCACHING_ENABLED);
|
FCB_STATE_READCACHING_ENABLED);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pVNetRootContext->nocache ||
|
if (pVNetRootContext->nocache ||
|
||||||
(params.CreateOptions & FILE_NO_INTERMEDIATE_BUFFERING)) {
|
(params.CreateOptions & FILE_NO_INTERMEDIATE_BUFFERING)) {
|
||||||
DbgP("nfs41_Create: disabling buffering\n");
|
DbgP("nfs41_Create: disabling buffering\n");
|
||||||
SrvOpen->BufferingFlags = FCB_STATE_DISABLE_LOCAL_BUFFERING;
|
SrvOpen->BufferingFlags = FCB_STATE_DISABLE_LOCAL_BUFFERING;
|
||||||
|
} else if (!entry->u.Open.deleg_type &&
|
||||||
|
(params.DesiredAccess &
|
||||||
|
(FILE_READ_DATA | FILE_WRITE_DATA | FILE_APPEND_DATA))) {
|
||||||
|
nfs41_srvopen_list_entry *oentry;
|
||||||
|
DbgP("nfs41_Create: received no delegations: srv_open=%p "
|
||||||
|
"ctime=%llu\n", SrvOpen, entry->u.Open.changeattr);
|
||||||
|
oentry = RxAllocatePoolWithTag(NonPagedPool,
|
||||||
|
sizeof(nfs41_srvopen_list_entry), NFS41_MM_POOLTAG);
|
||||||
|
if (oentry == NULL) {
|
||||||
|
status = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
oentry->srv_open = SrvOpen;
|
||||||
|
oentry->nfs41_fobx = nfs41_fobx;
|
||||||
|
oentry->ChangeTime = entry->u.Open.changeattr;
|
||||||
|
oentry->skip = FALSE;
|
||||||
|
nfs41_AddEntry(srvopenLock, openlist, oentry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3609,6 +3611,34 @@ ULONG nfs41_ExtendForNonCache(
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VOID nfs41_remove_srvopen_entry(
|
||||||
|
PMRX_SRV_OPEN SrvOpen)
|
||||||
|
{
|
||||||
|
PLIST_ENTRY pEntry;
|
||||||
|
nfs41_srvopen_list_entry *cur;
|
||||||
|
ExAcquireFastMutex(&srvopenLock);
|
||||||
|
|
||||||
|
pEntry = openlist->head.Flink;
|
||||||
|
DbgP("nfs41_remove_srvopen_entry: Looking for srv_open=%p\n", SrvOpen);
|
||||||
|
while (!IsListEmpty(&openlist->head)) {
|
||||||
|
cur = (nfs41_srvopen_list_entry *)CONTAINING_RECORD(pEntry,
|
||||||
|
nfs41_srvopen_list_entry, next);
|
||||||
|
if (cur->srv_open == SrvOpen) {
|
||||||
|
DbgP("nfs41_remove_srvopen_entry: Found match\n");
|
||||||
|
RemoveEntryList(pEntry);
|
||||||
|
RxFreePool(cur);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* place an upcall for this srv_open */
|
||||||
|
if (pEntry->Flink == &openlist->head) {
|
||||||
|
DbgP("nfs41_remove_srvopen_entry: reached end of the list\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
pEntry = pEntry->Flink;
|
||||||
|
}
|
||||||
|
ExReleaseFastMutex(&srvopenLock);
|
||||||
|
}
|
||||||
|
|
||||||
NTSTATUS map_close_errors(
|
NTSTATUS map_close_errors(
|
||||||
DWORD status)
|
DWORD status)
|
||||||
{
|
{
|
||||||
|
|
@ -3644,6 +3674,12 @@ NTSTATUS nfs41_CloseSrvOpen(
|
||||||
DbgEn();
|
DbgEn();
|
||||||
print_debug_header(RxContext);
|
print_debug_header(RxContext);
|
||||||
|
|
||||||
|
if (!nfs41_fobx->deleg_type && !nfs41_fcb->StandardInfo.Directory &&
|
||||||
|
(SrvOpen->DesiredAccess &
|
||||||
|
(FILE_READ_DATA | FILE_WRITE_DATA | FILE_APPEND_DATA))) {
|
||||||
|
nfs41_remove_srvopen_entry(SrvOpen);
|
||||||
|
}
|
||||||
|
|
||||||
status = nfs41_UpcallCreate(NFS41_CLOSE, &nfs41_fobx->sec_ctx,
|
status = nfs41_UpcallCreate(NFS41_CLOSE, &nfs41_fobx->sec_ctx,
|
||||||
pVNetRootContext->session, nfs41_fobx->nfs41_open_state,
|
pVNetRootContext->session, nfs41_fobx->nfs41_open_state,
|
||||||
pNetRootContext->nfs41d_version, &entry);
|
pNetRootContext->nfs41d_version, &entry);
|
||||||
|
|
@ -4027,6 +4063,35 @@ out:
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VOID nfs41_update_srvopen_list(
|
||||||
|
PMRX_SRV_OPEN SrvOpen,
|
||||||
|
ULONGLONG ChangeTime)
|
||||||
|
{
|
||||||
|
PLIST_ENTRY pEntry;
|
||||||
|
nfs41_srvopen_list_entry *cur;
|
||||||
|
ExAcquireFastMutex(&srvopenLock);
|
||||||
|
pEntry = openlist->head.Flink;
|
||||||
|
DbgP("nfs41_update_srvopen_list: Looking for srv_open=%p\n", SrvOpen);
|
||||||
|
while (!IsListEmpty(&openlist->head)) {
|
||||||
|
cur = (nfs41_srvopen_list_entry *)CONTAINING_RECORD(pEntry,
|
||||||
|
nfs41_srvopen_list_entry, next);
|
||||||
|
if (cur->srv_open == SrvOpen &&
|
||||||
|
cur->ChangeTime != ChangeTime) {
|
||||||
|
DbgP("nfs41_update_srvopen_list: Found match: updating %llu to "
|
||||||
|
"%llu\n", cur->ChangeTime, ChangeTime);
|
||||||
|
cur->ChangeTime = ChangeTime;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* place an upcall for this srv_open */
|
||||||
|
if (pEntry->Flink == &openlist->head) {
|
||||||
|
DbgP("nfs41_update_srvopen_list: reached end of the list\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
pEntry = pEntry->Flink;
|
||||||
|
}
|
||||||
|
ExReleaseFastMutex(&srvopenLock);
|
||||||
|
}
|
||||||
|
|
||||||
void print_nfs3_attrs(
|
void print_nfs3_attrs(
|
||||||
nfs3_attrs *attrs)
|
nfs3_attrs *attrs)
|
||||||
{
|
{
|
||||||
|
|
@ -4152,6 +4217,13 @@ NTSTATUS nfs41_SetEaInformation(
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
status = map_setea_error(entry->status);
|
status = map_setea_error(entry->status);
|
||||||
|
if (!status) {
|
||||||
|
if (!nfs41_fobx->deleg_type && entry->u.SetEa.ChangeTime &&
|
||||||
|
(SrvOpen->DesiredAccess &
|
||||||
|
(FILE_READ_DATA | FILE_WRITE_DATA | FILE_APPEND_DATA)))
|
||||||
|
nfs41_update_srvopen_list(SrvOpen, entry->u.SetEa.ChangeTime);
|
||||||
|
nfs41_fcb->changeattr = entry->u.SetEa.ChangeTime;
|
||||||
|
}
|
||||||
RxFreePool(entry);
|
RxFreePool(entry);
|
||||||
out:
|
out:
|
||||||
#ifdef ENABLE_TIMINGS
|
#ifdef ENABLE_TIMINGS
|
||||||
|
|
@ -4441,6 +4513,7 @@ NTSTATUS nfs41_SetSecurityInformation(
|
||||||
NFS41GetNetRootExtension(SrvOpen->pVNetRoot->pNetRoot);
|
NFS41GetNetRootExtension(SrvOpen->pVNetRoot->pNetRoot);
|
||||||
__notnull PSECURITY_DESCRIPTOR sec_desc =
|
__notnull PSECURITY_DESCRIPTOR sec_desc =
|
||||||
RxContext->CurrentIrpSp->Parameters.SetSecurity.SecurityDescriptor;
|
RxContext->CurrentIrpSp->Parameters.SetSecurity.SecurityDescriptor;
|
||||||
|
__notnull PNFS41_FCB nfs41_fcb = NFS41GetFcbExtension(RxContext->pFcb);
|
||||||
SECURITY_INFORMATION info_class =
|
SECURITY_INFORMATION info_class =
|
||||||
RxContext->CurrentIrpSp->Parameters.SetSecurity.SecurityInformation;
|
RxContext->CurrentIrpSp->Parameters.SetSecurity.SecurityInformation;
|
||||||
#ifdef ENABLE_TIMINGS
|
#ifdef ENABLE_TIMINGS
|
||||||
|
|
@ -4497,6 +4570,13 @@ NTSTATUS nfs41_SetSecurityInformation(
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
status = map_query_acl_error(entry->status);
|
status = map_query_acl_error(entry->status);
|
||||||
|
if (!status) {
|
||||||
|
if (!nfs41_fobx->deleg_type && entry->u.Acl.ChangeTime &&
|
||||||
|
(SrvOpen->DesiredAccess &
|
||||||
|
(FILE_READ_DATA | FILE_WRITE_DATA | FILE_APPEND_DATA)))
|
||||||
|
nfs41_update_srvopen_list(SrvOpen, entry->u.Acl.ChangeTime);
|
||||||
|
nfs41_fcb->changeattr = entry->u.Acl.ChangeTime;
|
||||||
|
}
|
||||||
RxFreePool(entry);
|
RxFreePool(entry);
|
||||||
out:
|
out:
|
||||||
#ifdef ENABLE_TIMINGS
|
#ifdef ENABLE_TIMINGS
|
||||||
|
|
@ -4838,6 +4918,13 @@ NTSTATUS nfs41_SetFileInformation(
|
||||||
}
|
}
|
||||||
|
|
||||||
status = map_setfile_error(entry->status);
|
status = map_setfile_error(entry->status);
|
||||||
|
if (!status) {
|
||||||
|
if (!nfs41_fobx->deleg_type && entry->u.SetFile.ChangeTime &&
|
||||||
|
(SrvOpen->DesiredAccess &
|
||||||
|
(FILE_READ_DATA | FILE_WRITE_DATA | FILE_APPEND_DATA)))
|
||||||
|
nfs41_update_srvopen_list(SrvOpen, entry->u.SetFile.ChangeTime);
|
||||||
|
nfs41_fcb->changeattr = entry->u.SetFile.ChangeTime;
|
||||||
|
}
|
||||||
RxFreePool(entry);
|
RxFreePool(entry);
|
||||||
out:
|
out:
|
||||||
#ifdef ENABLE_TIMINGS
|
#ifdef ENABLE_TIMINGS
|
||||||
|
|
@ -4936,9 +5023,15 @@ void print_readwrite_args(
|
||||||
}
|
}
|
||||||
|
|
||||||
void enable_caching(
|
void enable_caching(
|
||||||
PMRX_SRV_OPEN SrvOpen)
|
PMRX_SRV_OPEN SrvOpen,
|
||||||
|
PNFS41_FOBX nfs41_fobx,
|
||||||
|
ULONGLONG ChangeTime)
|
||||||
{
|
{
|
||||||
ULONG flag = 0;
|
ULONG flag = 0;
|
||||||
|
PLIST_ENTRY pEntry;
|
||||||
|
nfs41_srvopen_list_entry *cur;
|
||||||
|
BOOLEAN found = FALSE;
|
||||||
|
|
||||||
if (SrvOpen->DesiredAccess & FILE_READ_DATA)
|
if (SrvOpen->DesiredAccess & FILE_READ_DATA)
|
||||||
flag = ENABLE_READ_CACHING;
|
flag = ENABLE_READ_CACHING;
|
||||||
if (SrvOpen->DesiredAccess & FILE_WRITE_DATA)
|
if (SrvOpen->DesiredAccess & FILE_WRITE_DATA)
|
||||||
|
|
@ -4953,6 +5046,39 @@ void enable_caching(
|
||||||
return;
|
return;
|
||||||
|
|
||||||
RxChangeBufferingState((PSRV_OPEN)SrvOpen, ULongToPtr(flag), 1);
|
RxChangeBufferingState((PSRV_OPEN)SrvOpen, ULongToPtr(flag), 1);
|
||||||
|
|
||||||
|
ExAcquireFastMutex(&srvopenLock);
|
||||||
|
pEntry = openlist->head.Flink;
|
||||||
|
DbgP("enable_caching: Looking for srv_open=%p\n", SrvOpen);
|
||||||
|
while (!IsListEmpty(&openlist->head)) {
|
||||||
|
cur = (nfs41_srvopen_list_entry *)CONTAINING_RECORD(pEntry,
|
||||||
|
nfs41_srvopen_list_entry, next);
|
||||||
|
if (cur->srv_open == SrvOpen) {
|
||||||
|
DbgP("enable_caching: Found match\n");
|
||||||
|
cur->skip = FALSE;
|
||||||
|
found = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (pEntry->Flink == &openlist->head) {
|
||||||
|
DbgP("enable_caching: reached end of the list\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
pEntry = pEntry->Flink;
|
||||||
|
}
|
||||||
|
if (!found && nfs41_fobx->deleg_type) {
|
||||||
|
nfs41_srvopen_list_entry *oentry;
|
||||||
|
DbgP("enable_caching: delegation recalled: srv_open=%p\n", SrvOpen);
|
||||||
|
oentry = RxAllocatePoolWithTag(NonPagedPool,
|
||||||
|
sizeof(nfs41_srvopen_list_entry), NFS41_MM_POOLTAG);
|
||||||
|
if (oentry == NULL) return;
|
||||||
|
oentry->srv_open = SrvOpen;
|
||||||
|
oentry->nfs41_fobx = nfs41_fobx;
|
||||||
|
oentry->ChangeTime = ChangeTime;
|
||||||
|
oentry->skip = FALSE;
|
||||||
|
InsertTailList(&openlist->head, &oentry->next);
|
||||||
|
nfs41_fobx->deleg_type = 0;
|
||||||
|
}
|
||||||
|
ExReleaseFastMutex(&srvopenLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS map_readwrite_errors(
|
NTSTATUS map_readwrite_errors(
|
||||||
|
|
@ -5029,15 +5155,15 @@ NTSTATUS nfs41_Read(
|
||||||
RxContext->IoStatusBlock.Information = entry->u.ReadWrite.len;
|
RxContext->IoStatusBlock.Information = entry->u.ReadWrite.len;
|
||||||
nfs41_fcb->Flags = 0;
|
nfs41_fcb->Flags = 0;
|
||||||
|
|
||||||
if (pVNetRootContext->nocoherence &&
|
if ((!BooleanFlagOn(LowIoContext->ParamsFor.ReadWrite.Flags,
|
||||||
(!BooleanFlagOn(LowIoContext->ParamsFor.ReadWrite.Flags,
|
|
||||||
LOWIO_READWRITEFLAG_PAGING_IO) &&
|
LOWIO_READWRITEFLAG_PAGING_IO) &&
|
||||||
(SrvOpen->DesiredAccess & FILE_READ_DATA) &&
|
(SrvOpen->DesiredAccess & FILE_READ_DATA) &&
|
||||||
!pVNetRootContext->nocache &&
|
!pVNetRootContext->nocache &&
|
||||||
!(SrvOpen->BufferingFlags &
|
!(SrvOpen->BufferingFlags &
|
||||||
(FCB_STATE_READBUFFERING_ENABLED |
|
(FCB_STATE_READBUFFERING_ENABLED |
|
||||||
FCB_STATE_READCACHING_ENABLED))))
|
FCB_STATE_READCACHING_ENABLED)))) {
|
||||||
enable_caching(SrvOpen);
|
enable_caching(SrvOpen, nfs41_fobx, nfs41_fcb->changeattr);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
status = map_readwrite_errors(entry->status);
|
status = map_readwrite_errors(entry->status);
|
||||||
RxContext->CurrentIrp->IoStatus.Status = status;
|
RxContext->CurrentIrp->IoStatus.Status = status;
|
||||||
|
|
@ -5123,19 +5249,21 @@ NTSTATUS nfs41_Write(
|
||||||
status = RxContext->CurrentIrp->IoStatus.Status = STATUS_SUCCESS;
|
status = RxContext->CurrentIrp->IoStatus.Status = STATUS_SUCCESS;
|
||||||
RxContext->IoStatusBlock.Information = entry->u.ReadWrite.len;
|
RxContext->IoStatusBlock.Information = entry->u.ReadWrite.len;
|
||||||
nfs41_fcb->Flags = 0;
|
nfs41_fcb->Flags = 0;
|
||||||
|
nfs41_fcb->changeattr = entry->u.ReadWrite.ChangeTime;
|
||||||
|
|
||||||
//re-enable write buffering
|
//re-enable write buffering
|
||||||
if (pVNetRootContext->nocoherence &&
|
if ((!BooleanFlagOn(LowIoContext->ParamsFor.ReadWrite.Flags,
|
||||||
(!BooleanFlagOn(LowIoContext->ParamsFor.ReadWrite.Flags,
|
|
||||||
LOWIO_READWRITEFLAG_PAGING_IO) &&
|
LOWIO_READWRITEFLAG_PAGING_IO) &&
|
||||||
(SrvOpen->DesiredAccess & FILE_WRITE_DATA) &&
|
(SrvOpen->DesiredAccess & (FILE_WRITE_DATA | FILE_APPEND_DATA)) &&
|
||||||
(SrvOpen->DesiredAccess & FILE_READ_DATA) &&
|
|
||||||
!pVNetRootContext->write_thru &&
|
!pVNetRootContext->write_thru &&
|
||||||
!pVNetRootContext->nocache &&
|
!pVNetRootContext->nocache &&
|
||||||
!(SrvOpen->BufferingFlags &
|
!(SrvOpen->BufferingFlags &
|
||||||
(FCB_STATE_WRITEBUFFERING_ENABLED |
|
(FCB_STATE_WRITEBUFFERING_ENABLED |
|
||||||
FCB_STATE_WRITECACHING_ENABLED))))
|
FCB_STATE_WRITECACHING_ENABLED)))) {
|
||||||
enable_caching(SrvOpen);
|
enable_caching(SrvOpen, nfs41_fobx, nfs41_fcb->changeattr);
|
||||||
|
} else if (!nfs41_fobx->deleg_type)
|
||||||
|
nfs41_update_srvopen_list(SrvOpen, entry->u.ReadWrite.ChangeTime);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
status = map_readwrite_errors(entry->status);
|
status = map_readwrite_errors(entry->status);
|
||||||
RxContext->CurrentIrp->IoStatus.Status = status;
|
RxContext->CurrentIrp->IoStatus.Status = status;
|
||||||
|
|
@ -5765,6 +5893,83 @@ NTSTATUS nfs41_init_ops()
|
||||||
return(STATUS_SUCCESS);
|
return(STATUS_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define RELATIVE(wait) (-(wait))
|
||||||
|
#define NANOSECONDS(nanos) (((signed __int64)(nanos)) / 100L)
|
||||||
|
#define MICROSECONDS(micros) (((signed __int64)(micros)) * NANOSECONDS(1000L))
|
||||||
|
#define MILLISECONDS(milli) (((signed __int64)(milli)) * MICROSECONDS(1000L))
|
||||||
|
#define SECONDS(seconds) (((signed __int64)(seconds)) * MILLISECONDS(1000L))
|
||||||
|
|
||||||
|
KSTART_ROUTINE srvopen_main;
|
||||||
|
VOID srvopen_main(PVOID ctx)
|
||||||
|
{
|
||||||
|
NTSTATUS status;
|
||||||
|
LARGE_INTEGER timeout;
|
||||||
|
|
||||||
|
DbgEn();
|
||||||
|
timeout.QuadPart = RELATIVE(SECONDS(30));
|
||||||
|
while(1) {
|
||||||
|
PLIST_ENTRY pEntry;
|
||||||
|
nfs41_srvopen_list_entry *cur;
|
||||||
|
status = KeDelayExecutionThread(KernelMode, TRUE, &timeout);
|
||||||
|
ExAcquireFastMutex(&srvopenLock);
|
||||||
|
pEntry = openlist->head.Flink;
|
||||||
|
while (!IsListEmpty(&openlist->head)) {
|
||||||
|
PNFS41_V_NET_ROOT_EXTENSION pVNetRootContext;
|
||||||
|
PNFS41_NETROOT_EXTENSION pNetRootContext;
|
||||||
|
nfs41_updowncall_entry *entry;
|
||||||
|
FILE_BASIC_INFORMATION binfo;
|
||||||
|
PNFS41_FCB nfs41_fcb;
|
||||||
|
cur = (nfs41_srvopen_list_entry *)CONTAINING_RECORD(pEntry,
|
||||||
|
nfs41_srvopen_list_entry, next);
|
||||||
|
|
||||||
|
DbgP("srvopen_main: Checking attributes for srv_open=%p "
|
||||||
|
"change_time=%llu skipping=%d\n", cur->srv_open,
|
||||||
|
cur->ChangeTime, cur->skip);
|
||||||
|
if (cur->skip) goto out;
|
||||||
|
pVNetRootContext =
|
||||||
|
NFS41GetVNetRootExtension(cur->srv_open->pVNetRoot);
|
||||||
|
pNetRootContext =
|
||||||
|
NFS41GetNetRootExtension(cur->srv_open->pVNetRoot->pNetRoot);
|
||||||
|
/* place an upcall for this srv_open */
|
||||||
|
status = nfs41_UpcallCreate(NFS41_FILE_QUERY,
|
||||||
|
&cur->nfs41_fobx->sec_ctx, pVNetRootContext->session,
|
||||||
|
cur->nfs41_fobx->nfs41_open_state,
|
||||||
|
pNetRootContext->nfs41d_version, &entry);
|
||||||
|
if (status)
|
||||||
|
goto out;
|
||||||
|
entry->u.QueryFile.InfoClass = FileBasicInformation;
|
||||||
|
entry->u.QueryFile.buf = &binfo;
|
||||||
|
entry->u.QueryFile.buf_len = sizeof(binfo);
|
||||||
|
|
||||||
|
if (nfs41_UpcallWaitForReply(entry) != STATUS_SUCCESS) {
|
||||||
|
status = STATUS_INTERNAL_ERROR;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
if (cur->ChangeTime != entry->u.QueryFile.ChangeTime) {
|
||||||
|
ULONG flag = DISABLE_CACHING;
|
||||||
|
DbgP("srvopen_main: old ctime=%llu new_ctime=%llu\n",
|
||||||
|
cur->ChangeTime, entry->u.QueryFile.ChangeTime);
|
||||||
|
DbgP("************ Invalidate the cache ************\n");
|
||||||
|
RxChangeBufferingState((PSRV_OPEN)cur->srv_open,
|
||||||
|
ULongToPtr(flag), 1);
|
||||||
|
cur->ChangeTime = entry->u.QueryFile.ChangeTime;
|
||||||
|
cur->skip = TRUE;
|
||||||
|
}
|
||||||
|
nfs41_fcb = (PNFS41_FCB)cur->srv_open->pFcb->Context;
|
||||||
|
nfs41_fcb->changeattr = entry->u.QueryFile.ChangeTime;
|
||||||
|
RxFreePool(entry);
|
||||||
|
out:
|
||||||
|
if (pEntry->Flink == &openlist->head) {
|
||||||
|
DbgP("srvopen_main: reached end of the list\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
pEntry = pEntry->Flink;
|
||||||
|
}
|
||||||
|
ExReleaseFastMutex(&srvopenLock);
|
||||||
|
}
|
||||||
|
DbgEx();
|
||||||
|
}
|
||||||
|
|
||||||
NTSTATUS DriverEntry(
|
NTSTATUS DriverEntry(
|
||||||
IN PDRIVER_OBJECT drv,
|
IN PDRIVER_OBJECT drv,
|
||||||
IN PUNICODE_STRING path)
|
IN PUNICODE_STRING path)
|
||||||
|
|
@ -5774,6 +5979,8 @@ NTSTATUS DriverEntry(
|
||||||
UNICODE_STRING dev_name, user_dev_name;
|
UNICODE_STRING dev_name, user_dev_name;
|
||||||
PNFS41_DEVICE_EXTENSION dev_exts;
|
PNFS41_DEVICE_EXTENSION dev_exts;
|
||||||
TIME_FIELDS jan_1_1970 = {1970, 1, 1, 0, 0, 0, 0, 0};
|
TIME_FIELDS jan_1_1970 = {1970, 1, 1, 0, 0, 0, 0, 0};
|
||||||
|
ACCESS_MASK mask = 0;
|
||||||
|
OBJECT_ATTRIBUTES oattrs;
|
||||||
|
|
||||||
DbgEn();
|
DbgEn();
|
||||||
|
|
||||||
|
|
@ -5823,6 +6030,7 @@ NTSTATUS DriverEntry(
|
||||||
ExInitializeFastMutex(&downcallLock);
|
ExInitializeFastMutex(&downcallLock);
|
||||||
ExInitializeFastMutex(&xidLock);
|
ExInitializeFastMutex(&xidLock);
|
||||||
ExInitializeFastMutex(&openOwnerLock);
|
ExInitializeFastMutex(&openOwnerLock);
|
||||||
|
ExInitializeFastMutex(&srvopenLock);
|
||||||
upcall = RxAllocatePoolWithTag(NonPagedPool, sizeof(nfs41_updowncall_list),
|
upcall = RxAllocatePoolWithTag(NonPagedPool, sizeof(nfs41_updowncall_list),
|
||||||
NFS41_MM_POOLTAG);
|
NFS41_MM_POOLTAG);
|
||||||
if (upcall == NULL)
|
if (upcall == NULL)
|
||||||
|
|
@ -5835,6 +6043,23 @@ NTSTATUS DriverEntry(
|
||||||
goto out_unregister;
|
goto out_unregister;
|
||||||
}
|
}
|
||||||
InitializeListHead(&downcall->head);
|
InitializeListHead(&downcall->head);
|
||||||
|
openlist = RxAllocatePoolWithTag(NonPagedPool, sizeof(nfs41_srvopen_list),
|
||||||
|
NFS41_MM_POOLTAG);
|
||||||
|
if (openlist == NULL) {
|
||||||
|
RxFreePool(upcall);
|
||||||
|
RxFreePool(downcall);
|
||||||
|
goto out_unregister;
|
||||||
|
}
|
||||||
|
InitializeListHead(&openlist->head);
|
||||||
|
InitializeObjectAttributes(&oattrs, NULL, OBJ_KERNEL_HANDLE, NULL, NULL);
|
||||||
|
status = PsCreateSystemThread(&dev_exts->openlistHandle, mask,
|
||||||
|
&oattrs, NULL, NULL, &srvopen_main, NULL);
|
||||||
|
if (status != STATUS_SUCCESS) {
|
||||||
|
RxFreePool(upcall);
|
||||||
|
RxFreePool(downcall);
|
||||||
|
RxFreePool(openlist);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
drv->DriverUnload = nfs41_driver_unload;
|
drv->DriverUnload = nfs41_driver_unload;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue