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>
This commit is contained in:
Родитель
4b44b40e04
Коммит
652f89f64f
|
@ -39,6 +39,8 @@
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
#include <linux/errno.h>
|
#include <linux/errno.h>
|
||||||
#include <linux/string.h>
|
#include <linux/string.h>
|
||||||
|
#include <linux/ratelimit.h>
|
||||||
|
#include <linux/printk.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/sunrpc/clnt.h>
|
#include <linux/sunrpc/clnt.h>
|
||||||
#include <linux/sunrpc/gss_api.h>
|
#include <linux/sunrpc/gss_api.h>
|
||||||
|
@ -894,6 +896,8 @@ out:
|
||||||
|
|
||||||
static int can_open_delegated(struct nfs_delegation *delegation, fmode_t fmode)
|
static int can_open_delegated(struct nfs_delegation *delegation, fmode_t fmode)
|
||||||
{
|
{
|
||||||
|
if (delegation == NULL)
|
||||||
|
return 0;
|
||||||
if ((delegation->type & fmode) != fmode)
|
if ((delegation->type & fmode) != fmode)
|
||||||
return 0;
|
return 0;
|
||||||
if (test_bit(NFS_DELEGATION_NEED_RECLAIM, &delegation->flags))
|
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)
|
||||||
}
|
}
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
delegation = rcu_dereference(nfsi->delegation);
|
delegation = rcu_dereference(nfsi->delegation);
|
||||||
if (delegation == NULL ||
|
if (!can_open_delegated(delegation, fmode)) {
|
||||||
!can_open_delegated(delegation, fmode)) {
|
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1091,7 +1094,12 @@ static struct nfs4_state *nfs4_opendata_to_nfs4_state(struct nfs4_opendata *data
|
||||||
if (delegation)
|
if (delegation)
|
||||||
delegation_flags = delegation->flags;
|
delegation_flags = delegation->flags;
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
if ((delegation_flags & 1UL<<NFS_DELEGATION_NEED_RECLAIM) == 0)
|
if (data->o_arg.claim == NFS4_OPEN_CLAIM_DELEGATE_CUR) {
|
||||||
|
pr_err_ratelimited("NFS: Broken NFSv4 server %s is "
|
||||||
|
"returning a delegation for "
|
||||||
|
"OPEN(CLAIM_DELEGATE_CUR)\n",
|
||||||
|
NFS_CLIENT(inode)->cl_server);
|
||||||
|
} else if ((delegation_flags & 1UL<<NFS_DELEGATION_NEED_RECLAIM) == 0)
|
||||||
nfs_inode_set_delegation(state->inode,
|
nfs_inode_set_delegation(state->inode,
|
||||||
data->owner->so_cred,
|
data->owner->so_cred,
|
||||||
&data->o_res);
|
&data->o_res);
|
||||||
|
@ -1423,11 +1431,9 @@ static void nfs4_open_prepare(struct rpc_task *task, void *calldata)
|
||||||
goto out_no_action;
|
goto out_no_action;
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
delegation = rcu_dereference(NFS_I(data->state->inode)->delegation);
|
delegation = rcu_dereference(NFS_I(data->state->inode)->delegation);
|
||||||
if (delegation != NULL &&
|
if (data->o_arg.claim != NFS4_OPEN_CLAIM_DELEGATE_CUR &&
|
||||||
test_bit(NFS_DELEGATION_NEED_RECLAIM, &delegation->flags) == 0) {
|
can_open_delegated(delegation, data->o_arg.fmode))
|
||||||
rcu_read_unlock();
|
goto unlock_no_action;
|
||||||
goto out_no_action;
|
|
||||||
}
|
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
}
|
}
|
||||||
/* Update sequence id. */
|
/* Update sequence id. */
|
||||||
|
@ -1444,6 +1450,8 @@ static void nfs4_open_prepare(struct rpc_task *task, void *calldata)
|
||||||
return;
|
return;
|
||||||
rpc_call_start(task);
|
rpc_call_start(task);
|
||||||
return;
|
return;
|
||||||
|
unlock_no_action:
|
||||||
|
rcu_read_unlock();
|
||||||
out_no_action:
|
out_no_action:
|
||||||
task->tk_action = NULL;
|
task->tk_action = NULL;
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче