lock: address differences in lock semantics
zero-length ranges: valid on windows, but nfs servers MUST return NFS4ERR_INVAL for LOCK with length=0. use MRxIsLockRealizable() to return STATUS_NOT_SUPPORTED for zero-length ranges (avoiding the lock upcall and rpc) ranges that extend past UINT64_MAX: not valid on windows. NFS expects length=UINT64_MAX for locking to end-of-file. use length=UINT64_MAX if length >= UINT64_MAX-offset (making lock ranges consistent with linux client) Signed-off-by: Casey Bodley <cbodley@citi.umich.edu>
This commit is contained in:
parent
2d252266c2
commit
d98da23d49
3 changed files with 18 additions and 2 deletions
|
|
@ -155,6 +155,13 @@ static int handle_lock(nfs41_upcall *upcall)
|
||||||
|
|
||||||
nfs41_lock_stateid_arg(state, &stateid);
|
nfs41_lock_stateid_arg(state, &stateid);
|
||||||
|
|
||||||
|
/* 18.10.3. Operation 12: LOCK - Create Lock
|
||||||
|
* "To lock the file from a specific offset through the end-of-file
|
||||||
|
* (no matter how long the file actually is) use a length field equal
|
||||||
|
* to NFS4_UINT64_MAX." */
|
||||||
|
if (args->length >= NFS4_UINT64_MAX - args->offset)
|
||||||
|
args->length = NFS4_UINT64_MAX;
|
||||||
|
|
||||||
status = nfs41_lock(state->session, &state->file, &state->owner,
|
status = nfs41_lock(state->session, &state->file, &state->owner,
|
||||||
type, args->offset, args->length, FALSE, TRUE, &stateid);
|
type, args->offset, args->length, FALSE, TRUE, &stateid);
|
||||||
if (status) {
|
if (status) {
|
||||||
|
|
@ -240,6 +247,10 @@ static int handle_unlock(nfs41_upcall *upcall)
|
||||||
if (safe_read(&buf, &buf_len, &offset, sizeof(LONGLONG))) break;
|
if (safe_read(&buf, &buf_len, &offset, sizeof(LONGLONG))) break;
|
||||||
if (safe_read(&buf, &buf_len, &length, sizeof(LONGLONG))) break;
|
if (safe_read(&buf, &buf_len, &length, sizeof(LONGLONG))) break;
|
||||||
|
|
||||||
|
/* do the same translation as LOCK, or the ranges won't match */
|
||||||
|
if (length >= NFS4_UINT64_MAX - offset)
|
||||||
|
length = NFS4_UINT64_MAX;
|
||||||
|
|
||||||
status = nfs41_unlock(state->session,
|
status = nfs41_unlock(state->session,
|
||||||
&state->file, offset, length, &stateid);
|
&state->file, offset, length, &stateid);
|
||||||
if (status == NFS4_OK) {
|
if (status == NFS4_OK) {
|
||||||
|
|
|
||||||
|
|
@ -67,8 +67,8 @@ typedef struct __readwrite_upcall_args {
|
||||||
} readwrite_upcall_args;
|
} readwrite_upcall_args;
|
||||||
|
|
||||||
typedef struct __lock_upcall_args {
|
typedef struct __lock_upcall_args {
|
||||||
LONGLONG offset;
|
uint64_t offset;
|
||||||
LONGLONG length;
|
uint64_t length;
|
||||||
BOOLEAN exclusive;
|
BOOLEAN exclusive;
|
||||||
BOOLEAN blocking;
|
BOOLEAN blocking;
|
||||||
} lock_upcall_args;
|
} lock_upcall_args;
|
||||||
|
|
|
||||||
|
|
@ -4404,6 +4404,11 @@ NTSTATUS nfs41_IsLockRealizable (
|
||||||
ByteOffset->QuadPart,Length->QuadPart,
|
ByteOffset->QuadPart,Length->QuadPart,
|
||||||
BooleanFlagOn(LowIoLockFlags, SL_EXCLUSIVE_LOCK),
|
BooleanFlagOn(LowIoLockFlags, SL_EXCLUSIVE_LOCK),
|
||||||
!BooleanFlagOn(LowIoLockFlags, SL_FAIL_IMMEDIATELY));
|
!BooleanFlagOn(LowIoLockFlags, SL_FAIL_IMMEDIATELY));
|
||||||
|
|
||||||
|
/* NFS lock operations with length=0 MUST fail with NFS4ERR_INVAL */
|
||||||
|
if (Length->QuadPart == 0)
|
||||||
|
status = STATUS_NOT_SUPPORTED;
|
||||||
|
|
||||||
DbgEx();
|
DbgEx();
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue