/*
* Deal with broken servers that hand out two
* delegations for the same file.
+ * Allow for upgrades to a WRITE delegation, but
+ * nothing else.
*/
dfprintk(FILE, "%s: server %s handed out "
"a duplicate delegation!\n",
__func__, clp->cl_hostname);
- if (delegation->type <= old_delegation->type) {
+ if (delegation->type == old_delegation->type ||
+ !(delegation->type & FMODE_WRITE)) {
freeme = delegation;
delegation = NULL;
goto out;
rcu_read_unlock();
}
-static void nfs_client_mark_return_all_delegations(struct nfs_client *clp)
-{
- nfs_client_mark_return_all_delegation_types(clp, FMODE_READ|FMODE_WRITE);
-}
-
static void nfs_delegation_run_state_manager(struct nfs_client *clp)
{
if (test_bit(NFS4CLNT_DELEGRETURN, &clp->cl_state))
nfs_free_delegation(delegation);
}
}
+EXPORT_SYMBOL_GPL(nfs_remove_bad_delegation);
/**
* nfs_expire_all_delegation_types
nfs_expire_all_delegation_types(clp, FMODE_READ|FMODE_WRITE);
}
-/**
- * nfs_handle_cb_pathdown - return all delegations after NFS4ERR_CB_PATH_DOWN
- * @clp: client to process
- *
- */
-void nfs_handle_cb_pathdown(struct nfs_client *clp)
-{
- if (clp == NULL)
- return;
- nfs_client_mark_return_all_delegations(clp);
-}
-
static void nfs_mark_return_unreferenced_delegations(struct nfs_server *server)
{
struct nfs_delegation *delegation;
* nfs4_copy_delegation_stateid - Copy inode's state ID information
* @dst: stateid data structure to fill in
* @inode: inode to check
+ * @flags: delegation type requirement
*
- * Returns one and fills in "dst->data" * if inode had a delegation,
- * otherwise zero is returned.
+ * Returns "true" and fills in "dst->data" * if inode had a delegation,
+ * otherwise "false" is returned.
*/
-int nfs4_copy_delegation_stateid(nfs4_stateid *dst, struct inode *inode)
+bool nfs4_copy_delegation_stateid(nfs4_stateid *dst, struct inode *inode,
+ fmode_t flags)
{
struct nfs_inode *nfsi = NFS_I(inode);
struct nfs_delegation *delegation;
- int ret = 0;
+ bool ret;
+ flags &= FMODE_READ|FMODE_WRITE;
rcu_read_lock();
delegation = rcu_dereference(nfsi->delegation);
- if (delegation != NULL) {
+ ret = (delegation != NULL && (delegation->type & flags) == flags);
+ if (ret) {
nfs4_stateid_copy(dst, &delegation->stateid);
- ret = 1;
+ nfs_mark_delegation_referenced(delegation);
}
rcu_read_unlock();
return ret;