diff --git a/daemon/lock.c b/daemon/lock.c index 5044259..1386577 100644 --- a/daemon/lock.c +++ b/daemon/lock.c @@ -155,6 +155,13 @@ static int handle_lock(nfs41_upcall *upcall) 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, type, args->offset, args->length, FALSE, TRUE, &stateid); 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, &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, &state->file, offset, length, &stateid); if (status == NFS4_OK) { diff --git a/daemon/upcall.h b/daemon/upcall.h index 2b1d4d0..6289d74 100644 --- a/daemon/upcall.h +++ b/daemon/upcall.h @@ -67,8 +67,8 @@ typedef struct __readwrite_upcall_args { } readwrite_upcall_args; typedef struct __lock_upcall_args { - LONGLONG offset; - LONGLONG length; + uint64_t offset; + uint64_t length; BOOLEAN exclusive; BOOLEAN blocking; } lock_upcall_args; diff --git a/sys/nfs41_driver.c b/sys/nfs41_driver.c index 77bf814..4c2c73a 100644 --- a/sys/nfs41_driver.c +++ b/sys/nfs41_driver.c @@ -4404,6 +4404,11 @@ NTSTATUS nfs41_IsLockRealizable ( ByteOffset->QuadPart,Length->QuadPart, BooleanFlagOn(LowIoLockFlags, SL_EXCLUSIVE_LOCK), !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(); return status; }