Skip to content

Commit cd9288f

Browse files
committed
NFSv4: Fix another bug in the close/open_downgrade code
James Drew reports another bug whereby the NFS client is now sending an OPEN_DOWNGRADE in a situation where it should really have sent a CLOSE: the client is opening the file for O_RDWR, but then trying to do a downgrade to O_RDONLY, which is not allowed by the NFSv4 spec. Reported-by: James Drews <[email protected]> Link: http://lkml.kernel.org/r/[email protected] Fixes: aee7af3 (NFSv4: Fix problems with close in the presence...) Cc: [email protected] # 2.6.33+ Signed-off-by: Trond Myklebust <[email protected]>
1 parent 080af20 commit cd9288f

File tree

1 file changed

+15
-15
lines changed

1 file changed

+15
-15
lines changed

fs/nfs/nfs4proc.c

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2618,23 +2618,23 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data)
26182618
is_rdwr = test_bit(NFS_O_RDWR_STATE, &state->flags);
26192619
is_rdonly = test_bit(NFS_O_RDONLY_STATE, &state->flags);
26202620
is_wronly = test_bit(NFS_O_WRONLY_STATE, &state->flags);
2621-
/* Calculate the current open share mode */
2622-
calldata->arg.fmode = 0;
2623-
if (is_rdonly || is_rdwr)
2624-
calldata->arg.fmode |= FMODE_READ;
2625-
if (is_wronly || is_rdwr)
2626-
calldata->arg.fmode |= FMODE_WRITE;
26272621
/* Calculate the change in open mode */
2622+
calldata->arg.fmode = 0;
26282623
if (state->n_rdwr == 0) {
2629-
if (state->n_rdonly == 0) {
2630-
call_close |= is_rdonly || is_rdwr;
2631-
calldata->arg.fmode &= ~FMODE_READ;
2632-
}
2633-
if (state->n_wronly == 0) {
2634-
call_close |= is_wronly || is_rdwr;
2635-
calldata->arg.fmode &= ~FMODE_WRITE;
2636-
}
2637-
}
2624+
if (state->n_rdonly == 0)
2625+
call_close |= is_rdonly;
2626+
else if (is_rdonly)
2627+
calldata->arg.fmode |= FMODE_READ;
2628+
if (state->n_wronly == 0)
2629+
call_close |= is_wronly;
2630+
else if (is_wronly)
2631+
calldata->arg.fmode |= FMODE_WRITE;
2632+
} else if (is_rdwr)
2633+
calldata->arg.fmode |= FMODE_READ|FMODE_WRITE;
2634+
2635+
if (calldata->arg.fmode == 0)
2636+
call_close |= is_rdwr;
2637+
26382638
if (!nfs4_valid_open_stateid(state))
26392639
call_close = 0;
26402640
spin_unlock(&state->owner->so_lock);

0 commit comments

Comments
 (0)