diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2011-12-09 19:05:58 -0500 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2011-12-09 19:05:58 -0500 |
commit | 652f89f64fabcdae9143ee2b4253cfa838fb0279 (patch) | |
tree | 3ab618ec5a8f74c86d610e95ed04afa7b3b0b849 /fs | |
parent | 4b44b40e04a758e2242ff4a3f7c15982801ec8bc (diff) |
NFSv4: Do not accept delegated opens when a delegation recall is in effect
...and report the servers that try to return a delegation when the client
is using the CLAIM_DELEG_CUR open mode. That behaviour is explicitly
forbidden in RFC3530.
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/nfs/nfs4proc.c | 24 |
1 files changed, 16 insertions, 8 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index be2bbac13817..d9f4d78c3413 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -39,6 +39,8 @@ | |||
39 | #include <linux/delay.h> | 39 | #include <linux/delay.h> |
40 | #include <linux/errno.h> | 40 | #include <linux/errno.h> |
41 | #include <linux/string.h> | 41 | #include <linux/string.h> |
42 | #include <linux/ratelimit.h> | ||
43 | #include <linux/printk.h> | ||
42 | #include <linux/slab.h> | 44 | #include <linux/slab.h> |
43 | #include <linux/sunrpc/clnt.h> | 45 | #include <linux/sunrpc/clnt.h> |
44 | #include <linux/sunrpc/gss_api.h> | 46 | #include <linux/sunrpc/gss_api.h> |
@@ -894,6 +896,8 @@ out: | |||
894 | 896 | ||
895 | static int can_open_delegated(struct nfs_delegation *delegation, fmode_t fmode) | 897 | static int can_open_delegated(struct nfs_delegation *delegation, fmode_t fmode) |
896 | { | 898 | { |
899 | if (delegation == NULL) | ||
900 | return 0; | ||
897 | if ((delegation->type & fmode) != fmode) | 901 | if ((delegation->type & fmode) != fmode) |
898 | return 0; | 902 | return 0; |
899 | if (test_bit(NFS_DELEGATION_NEED_RECLAIM, &delegation->flags)) | 903 | if (test_bit(NFS_DELEGATION_NEED_RECLAIM, &delegation->flags)) |
@@ -1036,8 +1040,7 @@ static struct nfs4_state *nfs4_try_open_cached(struct nfs4_opendata *opendata) | |||
1036 | } | 1040 | } |
1037 | rcu_read_lock(); | 1041 | rcu_read_lock(); |
1038 | delegation = rcu_dereference(nfsi->delegation); | 1042 | delegation = rcu_dereference(nfsi->delegation); |
1039 | if (delegation == NULL || | 1043 | if (!can_open_delegated(delegation, fmode)) { |
1040 | !can_open_delegated(delegation, fmode)) { | ||
1041 | rcu_read_unlock(); | 1044 | rcu_read_unlock(); |
1042 | break; | 1045 | break; |
1043 | } | 1046 | } |
@@ -1091,7 +1094,12 @@ static struct nfs4_state *nfs4_opendata_to_nfs4_state(struct nfs4_opendata *data | |||
1091 | if (delegation) | 1094 | if (delegation) |
1092 | delegation_flags = delegation->flags; | 1095 | delegation_flags = delegation->flags; |
1093 | rcu_read_unlock(); | 1096 | rcu_read_unlock(); |
1094 | if ((delegation_flags & 1UL<<NFS_DELEGATION_NEED_RECLAIM) == 0) | 1097 | if (data->o_arg.claim == NFS4_OPEN_CLAIM_DELEGATE_CUR) { |
1098 | pr_err_ratelimited("NFS: Broken NFSv4 server %s is " | ||
1099 | "returning a delegation for " | ||
1100 | "OPEN(CLAIM_DELEGATE_CUR)\n", | ||
1101 | NFS_CLIENT(inode)->cl_server); | ||
1102 | } else if ((delegation_flags & 1UL<<NFS_DELEGATION_NEED_RECLAIM) == 0) | ||
1095 | nfs_inode_set_delegation(state->inode, | 1103 | nfs_inode_set_delegation(state->inode, |
1096 | data->owner->so_cred, | 1104 | data->owner->so_cred, |
1097 | &data->o_res); | 1105 | &data->o_res); |
@@ -1423,11 +1431,9 @@ static void nfs4_open_prepare(struct rpc_task *task, void *calldata) | |||
1423 | goto out_no_action; | 1431 | goto out_no_action; |
1424 | rcu_read_lock(); | 1432 | rcu_read_lock(); |
1425 | delegation = rcu_dereference(NFS_I(data->state->inode)->delegation); | 1433 | delegation = rcu_dereference(NFS_I(data->state->inode)->delegation); |
1426 | if (delegation != NULL && | 1434 | if (data->o_arg.claim != NFS4_OPEN_CLAIM_DELEGATE_CUR && |
1427 | test_bit(NFS_DELEGATION_NEED_RECLAIM, &delegation->flags) == 0) { | 1435 | can_open_delegated(delegation, data->o_arg.fmode)) |
1428 | rcu_read_unlock(); | 1436 | goto unlock_no_action; |
1429 | goto out_no_action; | ||
1430 | } | ||
1431 | rcu_read_unlock(); | 1437 | rcu_read_unlock(); |
1432 | } | 1438 | } |
1433 | /* Update sequence id. */ | 1439 | /* Update sequence id. */ |
@@ -1444,6 +1450,8 @@ static void nfs4_open_prepare(struct rpc_task *task, void *calldata) | |||
1444 | return; | 1450 | return; |
1445 | rpc_call_start(task); | 1451 | rpc_call_start(task); |
1446 | return; | 1452 | return; |
1453 | unlock_no_action: | ||
1454 | rcu_read_unlock(); | ||
1447 | out_no_action: | 1455 | out_no_action: |
1448 | task->tk_action = NULL; | 1456 | task->tk_action = NULL; |
1449 | 1457 | ||