summaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorTrond Myklebust <trond.myklebust@primarydata.com>2018-03-20 16:43:20 -0400
committerAnna Schumaker <Anna.Schumaker@Netapp.com>2018-04-10 16:06:22 -0400
commitc01d36457dccf8e4c8991ab6570ff11554824710 (patch)
tree6373d3295bea0bcee2c567b58551597337a508e3 /fs
parentc135cb39a907b85aef5389c191b6f02cffbadb8a (diff)
NFSv4: Don't return the delegation when not needed by NFSv4.x (x>0)
Starting with NFSv4.1, the server is able to deduce the client id from the SEQUENCE op which means it can always figure out whether or not the client is holding a delegation on a file that is being changed. For that reason, RFC5661 does not require a delegation to be unconditionally recalled on operations such as SETATTR, RENAME, or REMOVE. Note that for now, we continue to return READ delegations since that is still expected by the Linux knfsd server. Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com> Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/nfs/delegation.c17
-rw-r--r--fs/nfs/delegation.h1
-rw-r--r--fs/nfs/nfs4proc.c16
3 files changed, 28 insertions, 6 deletions
diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c
index d8b47624fee2..a5cb44375100 100644
--- a/fs/nfs/delegation.c
+++ b/fs/nfs/delegation.c
@@ -19,6 +19,7 @@
19#include <linux/nfs_xdr.h> 19#include <linux/nfs_xdr.h>
20 20
21#include "nfs4_fs.h" 21#include "nfs4_fs.h"
22#include "nfs4session.h"
22#include "delegation.h" 23#include "delegation.h"
23#include "internal.h" 24#include "internal.h"
24#include "nfs4trace.h" 25#include "nfs4trace.h"
@@ -547,6 +548,22 @@ int nfs4_inode_return_delegation(struct inode *inode)
547 return err; 548 return err;
548} 549}
549 550
551/**
552 * nfs4_inode_make_writeable
553 * @inode: pointer to inode
554 *
555 * Make the inode writeable by returning the delegation if necessary
556 *
557 * Returns zero on success, or a negative errno value.
558 */
559int nfs4_inode_make_writeable(struct inode *inode)
560{
561 if (!nfs4_has_session(NFS_SERVER(inode)->nfs_client) ||
562 !nfs4_check_delegation(inode, FMODE_WRITE))
563 return nfs4_inode_return_delegation(inode);
564 return 0;
565}
566
550static void nfs_mark_return_if_closed_delegation(struct nfs_server *server, 567static void nfs_mark_return_if_closed_delegation(struct nfs_server *server,
551 struct nfs_delegation *delegation) 568 struct nfs_delegation *delegation)
552{ 569{
diff --git a/fs/nfs/delegation.h b/fs/nfs/delegation.h
index 185a09f37a89..dcc8a783a6e1 100644
--- a/fs/nfs/delegation.h
+++ b/fs/nfs/delegation.h
@@ -70,6 +70,7 @@ int nfs4_check_delegation(struct inode *inode, fmode_t flags);
70bool nfs4_delegation_flush_on_close(const struct inode *inode); 70bool nfs4_delegation_flush_on_close(const struct inode *inode);
71void nfs_inode_find_delegation_state_and_recover(struct inode *inode, 71void nfs_inode_find_delegation_state_and_recover(struct inode *inode,
72 const nfs4_stateid *stateid); 72 const nfs4_stateid *stateid);
73int nfs4_inode_make_writeable(struct inode *inode);
73 74
74#endif 75#endif
75 76
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 04978bfd6beb..24b5c80b8128 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -3877,7 +3877,7 @@ nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr,
3877 3877
3878 /* Return any delegations if we're going to change ACLs */ 3878 /* Return any delegations if we're going to change ACLs */
3879 if ((sattr->ia_valid & (ATTR_MODE|ATTR_UID|ATTR_GID)) != 0) 3879 if ((sattr->ia_valid & (ATTR_MODE|ATTR_UID|ATTR_GID)) != 0)
3880 nfs4_inode_return_delegation(inode); 3880 nfs4_inode_make_writeable(inode);
3881 3881
3882 status = nfs4_do_setattr(inode, cred, fattr, sattr, ctx, NULL, label); 3882 status = nfs4_do_setattr(inode, cred, fattr, sattr, ctx, NULL, label);
3883 if (status == 0) { 3883 if (status == 0) {
@@ -4210,8 +4210,12 @@ static int nfs4_proc_remove(struct inode *dir, struct dentry *dentry)
4210 struct inode *inode = d_inode(dentry); 4210 struct inode *inode = d_inode(dentry);
4211 int err; 4211 int err;
4212 4212
4213 if (inode) 4213 if (inode) {
4214 nfs4_inode_return_delegation(inode); 4214 if (inode->i_nlink == 1)
4215 nfs4_inode_return_delegation(inode);
4216 else
4217 nfs4_inode_make_writeable(inode);
4218 }
4215 do { 4219 do {
4216 err = _nfs4_proc_remove(dir, &dentry->d_name); 4220 err = _nfs4_proc_remove(dir, &dentry->d_name);
4217 trace_nfs4_remove(dir, &dentry->d_name, err); 4221 trace_nfs4_remove(dir, &dentry->d_name, err);
@@ -4284,7 +4288,7 @@ static void nfs4_proc_rename_setup(struct rpc_message *msg,
4284 struct inode *new_inode = d_inode(new_dentry); 4288 struct inode *new_inode = d_inode(new_dentry);
4285 4289
4286 if (old_inode) 4290 if (old_inode)
4287 nfs4_inode_return_delegation(old_inode); 4291 nfs4_inode_make_writeable(old_inode);
4288 if (new_inode) 4292 if (new_inode)
4289 nfs4_inode_return_delegation(new_inode); 4293 nfs4_inode_return_delegation(new_inode);
4290 msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_RENAME]; 4294 msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_RENAME];
@@ -4350,7 +4354,7 @@ static int _nfs4_proc_link(struct inode *inode, struct inode *dir, const struct
4350 } 4354 }
4351 arg.bitmask = nfs4_bitmask(server, res.label); 4355 arg.bitmask = nfs4_bitmask(server, res.label);
4352 4356
4353 nfs4_inode_return_delegation(inode); 4357 nfs4_inode_make_writeable(inode);
4354 4358
4355 status = nfs4_call_sync(server->client, server, &msg, &arg.seq_args, &res.seq_res, 1); 4359 status = nfs4_call_sync(server->client, server, &msg, &arg.seq_args, &res.seq_res, 1);
4356 if (!status) { 4360 if (!status) {
@@ -5345,7 +5349,7 @@ static int __nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t bufl
5345 i = buf_to_pages_noslab(buf, buflen, arg.acl_pages); 5349 i = buf_to_pages_noslab(buf, buflen, arg.acl_pages);
5346 if (i < 0) 5350 if (i < 0)
5347 return i; 5351 return i;
5348 nfs4_inode_return_delegation(inode); 5352 nfs4_inode_make_writeable(inode);
5349 ret = nfs4_call_sync(server->client, server, &msg, &arg.seq_args, &res.seq_res, 1); 5353 ret = nfs4_call_sync(server->client, server, &msg, &arg.seq_args, &res.seq_res, 1);
5350 5354
5351 /* 5355 /*