enforcing data consistency
given a delegation type received on open, set buffering flags accordingly. however, provide -o nocoherence mount options that will enable read/write buffering regardless
This commit is contained in:
parent
c22c2b6080
commit
fb87e417fc
3 changed files with 58 additions and 39 deletions
|
|
@ -602,6 +602,8 @@ static int handle_open(nfs41_upcall *upcall)
|
||||||
nfs_to_basic_info(&info, &args->basic_info);
|
nfs_to_basic_info(&info, &args->basic_info);
|
||||||
nfs_to_standard_info(&info, &args->std_info);
|
nfs_to_standard_info(&info, &args->std_info);
|
||||||
args->mode = info.mode;
|
args->mode = info.mode;
|
||||||
|
if (state->delegation.state)
|
||||||
|
args->deleg_type = state->delegation.state->state.type;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (status) {
|
if (status) {
|
||||||
|
|
@ -636,6 +638,8 @@ static int marshall_open(unsigned char *buffer, uint32_t *length, nfs41_upcall *
|
||||||
if (status) goto out;
|
if (status) goto out;
|
||||||
status = safe_write(&buffer, length, &args->changeattr, sizeof(args->changeattr));
|
status = safe_write(&buffer, length, &args->changeattr, sizeof(args->changeattr));
|
||||||
if (status) goto out;
|
if (status) goto out;
|
||||||
|
status = safe_write(&buffer, length, &args->deleg_type, sizeof(args->deleg_type));
|
||||||
|
if (status) goto out;
|
||||||
if (upcall->last_error == ERROR_REPARSE) {
|
if (upcall->last_error == ERROR_REPARSE) {
|
||||||
unsigned short len = (args->symlink.len + 1) * sizeof(WCHAR);
|
unsigned short len = (args->symlink.len + 1) * sizeof(WCHAR);
|
||||||
status = safe_write(&buffer, length, &args->symlink_embedded, sizeof(BOOLEAN));
|
status = safe_write(&buffer, length, &args->symlink_embedded, sizeof(BOOLEAN));
|
||||||
|
|
|
||||||
|
|
@ -55,6 +55,7 @@ typedef struct __open_upcall_args {
|
||||||
DWORD mode;
|
DWORD mode;
|
||||||
LONGLONG changeattr;
|
LONGLONG changeattr;
|
||||||
HANDLE srv_open;
|
HANDLE srv_open;
|
||||||
|
DWORD deleg_type;
|
||||||
BOOLEAN created;
|
BOOLEAN created;
|
||||||
BOOLEAN symlink_embedded;
|
BOOLEAN symlink_embedded;
|
||||||
} open_upcall_args;
|
} open_upcall_args;
|
||||||
|
|
|
||||||
|
|
@ -175,6 +175,7 @@ typedef struct _updowncall_entry {
|
||||||
DWORD mode;
|
DWORD mode;
|
||||||
LONGLONG changeattr;
|
LONGLONG changeattr;
|
||||||
HANDLE srv_open;
|
HANDLE srv_open;
|
||||||
|
DWORD deleg_type;
|
||||||
BOOLEAN symlink_embedded;
|
BOOLEAN symlink_embedded;
|
||||||
} Open;
|
} Open;
|
||||||
struct {
|
struct {
|
||||||
|
|
@ -311,6 +312,7 @@ 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];
|
||||||
|
|
@ -351,6 +353,7 @@ 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;
|
||||||
|
|
@ -1572,6 +1575,8 @@ NTSTATUS unmarshal_nfs41_open(
|
||||||
*buf += sizeof(DWORD);
|
*buf += sizeof(DWORD);
|
||||||
RtlCopyMemory(&cur->u.Open.changeattr, *buf, sizeof(LONGLONG));
|
RtlCopyMemory(&cur->u.Open.changeattr, *buf, sizeof(LONGLONG));
|
||||||
*buf += sizeof(LONGLONG);
|
*buf += sizeof(LONGLONG);
|
||||||
|
RtlCopyMemory(&cur->u.Open.deleg_type, *buf, sizeof(DWORD));
|
||||||
|
*buf += sizeof(DWORD);
|
||||||
if (cur->errno == ERROR_REPARSE) {
|
if (cur->errno == ERROR_REPARSE) {
|
||||||
RtlCopyMemory(&cur->u.Open.symlink_embedded, *buf, sizeof(BOOLEAN));
|
RtlCopyMemory(&cur->u.Open.symlink_embedded, *buf, sizeof(BOOLEAN));
|
||||||
*buf += sizeof(BOOLEAN);
|
*buf += sizeof(BOOLEAN);
|
||||||
|
|
@ -1591,8 +1596,9 @@ NTSTATUS unmarshal_nfs41_open(
|
||||||
cur->u.Open.symlink.MaximumLength);
|
cur->u.Open.symlink.MaximumLength);
|
||||||
DbgP("[open] ERROR_REPARSE -> '%wZ'\n", &cur->u.Open.symlink);
|
DbgP("[open] ERROR_REPARSE -> '%wZ'\n", &cur->u.Open.symlink);
|
||||||
}
|
}
|
||||||
DbgP("[open] open_state 0x%x mode %o changeattr 0x%x\n",
|
DbgP("[open] open_state 0x%x mode %o changeattr 0x%x deleg_type %d\n",
|
||||||
cur->open_state, cur->u.Open.mode, cur->u.Open.changeattr);
|
cur->open_state, cur->u.Open.mode, cur->u.Open.changeattr,
|
||||||
|
cur->u.Open.deleg_type);
|
||||||
out:
|
out:
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
@ -2488,6 +2494,7 @@ 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;
|
||||||
|
|
@ -2581,6 +2588,10 @@ 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,
|
||||||
|
|
@ -2783,6 +2794,7 @@ 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;
|
||||||
|
|
@ -3425,37 +3437,38 @@ NTSTATUS nfs41_Create(
|
||||||
SrvOpen->pVNetRoot->pNetRoot->pSrvCall,
|
SrvOpen->pVNetRoot->pNetRoot->pSrvCall,
|
||||||
SrvOpen, SrvOpen->Key, ULongToPtr(flag));
|
SrvOpen, SrvOpen->Key, ULongToPtr(flag));
|
||||||
} else if (!file_changed && !nfs41_fcb->StandardInfo.Directory) {
|
} else if (!file_changed && !nfs41_fcb->StandardInfo.Directory) {
|
||||||
#if 0
|
// windows does agressive write flushing (every 2s)
|
||||||
SrvOpen->BufferingFlags |= FCB_STATE_DISABLE_LOCAL_BUFFERING;
|
// thus we'll always turn on write buffering
|
||||||
#else
|
if ((!pVNetRootContext->nocoherence &&
|
||||||
// turn on read caching
|
(entry->u.Open.deleg_type == 2 &&
|
||||||
if (pVNetRootContext->nocache)
|
!(params.CreateOptions & FILE_WRITE_THROUGH))) ||
|
||||||
SrvOpen->BufferingFlags = FCB_STATE_DISABLE_LOCAL_BUFFERING;
|
(pVNetRootContext->nocoherence &&
|
||||||
else {
|
((params.DesiredAccess & FILE_WRITE_DATA ||
|
||||||
if (params.DesiredAccess & FILE_READ_DATA)
|
|
||||||
SrvOpen->BufferingFlags |=
|
|
||||||
(FCB_STATE_READBUFFERING_ENABLED |
|
|
||||||
FCB_STATE_READCACHING_ENABLED);
|
|
||||||
// turn on write caching only if the file opened for both reading
|
|
||||||
// and writingwe current CANT turn on write-only caching because
|
|
||||||
// RDBSS translates a write into a read first which leads to a
|
|
||||||
// NFS4ERR_IO error from the server because the file was opened
|
|
||||||
// read-only.
|
|
||||||
if (/*(params.DesiredAccess & FILE_READ_DATA) && */
|
|
||||||
(params.DesiredAccess & FILE_WRITE_DATA ||
|
|
||||||
params.DesiredAccess & FILE_APPEND_DATA) &&
|
params.DesiredAccess & FILE_APPEND_DATA) &&
|
||||||
!pVNetRootContext->write_thru)
|
!pVNetRootContext->write_thru &&
|
||||||
|
!(params.CreateOptions & FILE_WRITE_THROUGH)))) {
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
// if we received read delegation, turn on read buffering
|
||||||
|
if ((!pVNetRootContext->nocoherence &&
|
||||||
|
(entry->u.Open.deleg_type >= 1)) ||
|
||||||
|
(pVNetRootContext->nocoherence &&
|
||||||
|
(params.DesiredAccess & FILE_READ_DATA))) {
|
||||||
|
DbgP("nfs41_Create: enabling read buffering\n");
|
||||||
|
SrvOpen->BufferingFlags |=
|
||||||
|
(FCB_STATE_READBUFFERING_ENABLED |
|
||||||
|
FCB_STATE_READCACHING_ENABLED);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (params.CreateOptions & FILE_WRITE_THROUGH ||
|
if (pVNetRootContext->nocache ||
|
||||||
params.CreateOptions & FILE_NO_INTERMEDIATE_BUFFERING) {
|
(params.CreateOptions & FILE_NO_INTERMEDIATE_BUFFERING)) {
|
||||||
DbgP("Disable caching\n");
|
DbgP("nfs41_Create: disabling buffering\n");
|
||||||
SrvOpen->BufferingFlags |= FCB_STATE_DISABLE_LOCAL_BUFFERING;
|
SrvOpen->BufferingFlags = FCB_STATE_DISABLE_LOCAL_BUFFERING;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((params.CreateOptions & FILE_DELETE_ON_CLOSE) &&
|
if ((params.CreateOptions & FILE_DELETE_ON_CLOSE) &&
|
||||||
|
|
@ -4903,9 +4916,7 @@ void enable_caching(
|
||||||
if (!flag)
|
if (!flag)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
RxIndicateChangeOfBufferingStateForSrvOpen(
|
RxChangeBufferingState((PSRV_OPEN)SrvOpen, ULongToPtr(flag), 1);
|
||||||
SrvOpen->pVNetRoot->pNetRoot->pSrvCall,
|
|
||||||
SrvOpen, SrvOpen->Key, ULongToPtr(flag));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS map_readwrite_errors(
|
NTSTATUS map_readwrite_errors(
|
||||||
|
|
@ -4982,13 +4993,14 @@ 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 (!BooleanFlagOn(LowIoContext->ParamsFor.ReadWrite.Flags,
|
if (pVNetRootContext->nocoherence &&
|
||||||
|
(!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);
|
||||||
} else {
|
} else {
|
||||||
status = map_readwrite_errors(entry->status);
|
status = map_readwrite_errors(entry->status);
|
||||||
|
|
@ -5076,7 +5088,9 @@ NTSTATUS nfs41_Write(
|
||||||
RxContext->IoStatusBlock.Information = entry->u.ReadWrite.len;
|
RxContext->IoStatusBlock.Information = entry->u.ReadWrite.len;
|
||||||
nfs41_fcb->Flags = 0;
|
nfs41_fcb->Flags = 0;
|
||||||
|
|
||||||
if (!BooleanFlagOn(LowIoContext->ParamsFor.ReadWrite.Flags,
|
//re-enable write buffering
|
||||||
|
if (pVNetRootContext->nocoherence &&
|
||||||
|
(!BooleanFlagOn(LowIoContext->ParamsFor.ReadWrite.Flags,
|
||||||
LOWIO_READWRITEFLAG_PAGING_IO) &&
|
LOWIO_READWRITEFLAG_PAGING_IO) &&
|
||||||
(SrvOpen->DesiredAccess & FILE_WRITE_DATA) &&
|
(SrvOpen->DesiredAccess & FILE_WRITE_DATA) &&
|
||||||
(SrvOpen->DesiredAccess & FILE_READ_DATA) &&
|
(SrvOpen->DesiredAccess & FILE_READ_DATA) &&
|
||||||
|
|
@ -5084,7 +5098,7 @@ NTSTATUS nfs41_Write(
|
||||||
!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);
|
||||||
} else {
|
} else {
|
||||||
status = map_readwrite_errors(entry->status);
|
status = map_readwrite_errors(entry->status);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue