According to page 112 in RFC 7530, NFSv4 read operation should be allowed on a open state
with share access OPEN4_SHARE_ACCESS_WRITE to accommodate clients whose write
implementation may unavoidably do reads (e.g., due to buffer cache constraints).
This condition is taken care in normal flow in nfs4_read() in here:
https://github.com/nfs-ganesha/nfs-ganesha/blob/next/src/Protocols/NFS/nf...
But if the open has granted a write delegation(OPEN_DELEGATE_WRITE), then the check for
deleg state in nfs4_read() does not allow Read op as per RFC mentioned above but return
NFS4ERR_BAD_STATEID.
https://github.com/nfs-ganesha/nfs-ganesha/blob/next/src/Protocols/NFS/nf...
case STATE_TYPE_DELEG:
/* Check if the delegation state allows READ or
* if the open share state allows READ access
* in case of WRITE delegation */
sdeleg = &state_found->state_data.deleg;
if (!((sdeleg->sd_type & OPEN_DELEGATE_READ) ||
(sdeleg->share_access & OPEN4_SHARE_ACCESS_READ))) {
/* Invalid delegation for this operation. */
LogDebug(COMPONENT_STATE,
"Delegation type:%d state:%d",
sdeleg->sd_type,
sdeleg->sd_state);
res_READ4->status = NFS4ERR_BAD_STATEID;
goto out;
}
state_open = NULL;
break;
The ubuntu nfs client when it wants to write data, always opens file with
OPEN4_SHARE_ACCESS_WRITE and not OPEN4_SHARE_ACCESS_BOTH like other linux clients, so with
delegation enabled if we just do "echo data > file.txt ; cat file.txt", it
hangs forever with read op getting NFS4ERR_BAD_STATEID and client retrying forever.
I feel this whole block under 'case STATE_TYPE_DELEG' is not needed at all, as the
share access check will anyway happen below and we need not check the delegation state
while doing read operation.