diff options
author | Trond Myklebust <trond.myklebust@primarydata.com> | 2014-09-18 11:51:32 -0400 |
---|---|---|
committer | Trond Myklebust <trond.myklebust@primarydata.com> | 2014-09-18 13:04:22 -0400 |
commit | cd9288ffaea4359d5cfe2b8d264911506aed26a4 (patch) | |
tree | 82bddbe31030ef1c460d0df957afb55ff1d99283 /fs/nfs | |
parent | 080af20cc945d110f9912d01cf6b66f94a375b8d (diff) |
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 <drews@engr.wisc.edu>
Link: http://lkml.kernel.org/r/541AD7E5.8020409@engr.wisc.edu
Fixes: aee7af356e15 (NFSv4: Fix problems with close in the presence...)
Cc: stable@vger.kernel.org # 2.6.33+
Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Diffstat (limited to 'fs/nfs')
-rw-r--r-- | fs/nfs/nfs4proc.c | 30 |
1 files changed, 15 insertions, 15 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index ac2dd953fc18..6ca0c8e7a945 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -2618,23 +2618,23 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data) | |||
2618 | is_rdwr = test_bit(NFS_O_RDWR_STATE, &state->flags); | 2618 | is_rdwr = test_bit(NFS_O_RDWR_STATE, &state->flags); |
2619 | is_rdonly = test_bit(NFS_O_RDONLY_STATE, &state->flags); | 2619 | is_rdonly = test_bit(NFS_O_RDONLY_STATE, &state->flags); |
2620 | is_wronly = test_bit(NFS_O_WRONLY_STATE, &state->flags); | 2620 | 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; | ||
2627 | /* Calculate the change in open mode */ | 2621 | /* Calculate the change in open mode */ |
2622 | calldata->arg.fmode = 0; | ||
2628 | if (state->n_rdwr == 0) { | 2623 | if (state->n_rdwr == 0) { |
2629 | if (state->n_rdonly == 0) { | 2624 | if (state->n_rdonly == 0) |
2630 | call_close |= is_rdonly || is_rdwr; | 2625 | call_close |= is_rdonly; |
2631 | calldata->arg.fmode &= ~FMODE_READ; | 2626 | else if (is_rdonly) |
2632 | } | 2627 | calldata->arg.fmode |= FMODE_READ; |
2633 | if (state->n_wronly == 0) { | 2628 | if (state->n_wronly == 0) |
2634 | call_close |= is_wronly || is_rdwr; | 2629 | call_close |= is_wronly; |
2635 | calldata->arg.fmode &= ~FMODE_WRITE; | 2630 | else if (is_wronly) |
2636 | } | 2631 | calldata->arg.fmode |= FMODE_WRITE; |
2637 | } | 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 | |||
2638 | if (!nfs4_valid_open_stateid(state)) | 2638 | if (!nfs4_valid_open_stateid(state)) |
2639 | call_close = 0; | 2639 | call_close = 0; |
2640 | spin_unlock(&state->owner->so_lock); | 2640 | spin_unlock(&state->owner->so_lock); |