All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/8] Don't return delegations unnecessarily in NFSv4.1
@ 2018-03-20 20:43 Trond Myklebust
  2018-03-20 20:43 ` [PATCH 1/8] NFSv4: Fix nfs4_return_incompatible_delegation Trond Myklebust
  0 siblings, 1 reply; 9+ messages in thread
From: Trond Myklebust @ 2018-03-20 20:43 UTC (permalink / raw)
  To: Anna Schumaker; +Cc: linux-nfs

The following is a patch series that fixes up the delegation code so
that the NFSv4.1 client will attempt to hold on to a write delegation
across link(), rename() and sillyrename() operations, as well as
across chown, chmod and setacl.

The behaviour of the NFSv4.0 client should remain unchanged. Ditto
for the behaviour of the NFSv4.1 client concerning read delegations.

Trond Myklebust (8):
  NFSv4: Fix nfs4_return_incompatible_delegation
  NFS: Move the delegation return down into nfs4_proc_link()
  NFS: Move the delegation return down into nfs4_proc_remove()
  NFS: Move delegation recall into the NFSv4 callback for rename_setup()
  NFS: Add a delegation return into nfs4_proc_unlink_setup()
  NFS: Move the delegation return down into _nfs4_do_setattr()
  NFS: Remove the unused return_delegation() callback
  NFSv4: Don't return the delegation when not needed by NFSv4.x (x>0)

 fs/nfs/delegation.c     | 17 +++++++++++++++
 fs/nfs/delegation.h     |  1 +
 fs/nfs/dir.c            | 11 ++--------
 fs/nfs/inode.c          |  5 -----
 fs/nfs/nfs3proc.c       | 19 ++++++----------
 fs/nfs/nfs4proc.c       | 58 ++++++++++++++++++++++++++++++++++++++++---------
 fs/nfs/proc.c           | 19 ++++++----------
 fs/nfs/unlink.c         |  7 ++----
 include/linux/nfs_xdr.h |  9 ++++----
 9 files changed, 89 insertions(+), 57 deletions(-)

-- 
2.14.3


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH 1/8] NFSv4: Fix nfs4_return_incompatible_delegation
  2018-03-20 20:43 [PATCH 0/8] Don't return delegations unnecessarily in NFSv4.1 Trond Myklebust
@ 2018-03-20 20:43 ` Trond Myklebust
  2018-03-20 20:43   ` [PATCH 2/8] NFS: Move the delegation return down into nfs4_proc_link() Trond Myklebust
  0 siblings, 1 reply; 9+ messages in thread
From: Trond Myklebust @ 2018-03-20 20:43 UTC (permalink / raw)
  To: Anna Schumaker; +Cc: linux-nfs

The 'fmode' argument can take an FMODE_EXEC value, which we want to
filter out before comparing to the delegation type.

Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
---
 fs/nfs/nfs4proc.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 47f3c273245e..75b8ea08e6f7 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -1669,6 +1669,7 @@ static void nfs4_return_incompatible_delegation(struct inode *inode, fmode_t fmo
 {
 	struct nfs_delegation *delegation;
 
+	fmode &= FMODE_READ|FMODE_WRITE;
 	rcu_read_lock();
 	delegation = rcu_dereference(NFS_I(inode)->delegation);
 	if (delegation == NULL || (delegation->type & fmode) == fmode) {
-- 
2.14.3


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 2/8] NFS: Move the delegation return down into nfs4_proc_link()
  2018-03-20 20:43 ` [PATCH 1/8] NFSv4: Fix nfs4_return_incompatible_delegation Trond Myklebust
@ 2018-03-20 20:43   ` Trond Myklebust
  2018-03-20 20:43     ` [PATCH 3/8] NFS: Move the delegation return down into nfs4_proc_remove() Trond Myklebust
  0 siblings, 1 reply; 9+ messages in thread
From: Trond Myklebust @ 2018-03-20 20:43 UTC (permalink / raw)
  To: Anna Schumaker; +Cc: linux-nfs

Move the delegation return out of generic code.

Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
---
 fs/nfs/dir.c      | 2 --
 fs/nfs/nfs4proc.c | 2 ++
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index 2f3f86726f5b..b4549e54007d 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -1932,8 +1932,6 @@ nfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry)
 		old_dentry, dentry);
 
 	trace_nfs_link_enter(inode, dir, dentry);
-	NFS_PROTO(inode)->return_delegation(inode);
-
 	d_drop(dentry);
 	error = NFS_PROTO(dir)->link(inode, dir, &dentry->d_name);
 	if (error == 0) {
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 75b8ea08e6f7..8290a04907b0 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -4318,6 +4318,8 @@ static int _nfs4_proc_link(struct inode *inode, struct inode *dir, const struct
 	}
 	arg.bitmask = nfs4_bitmask(server, res.label);
 
+	nfs4_inode_return_delegation(inode);
+
 	status = nfs4_call_sync(server->client, server, &msg, &arg.seq_args, &res.seq_res, 1);
 	if (!status) {
 		update_changeattr(dir, &res.cinfo, res.fattr->time_start);
-- 
2.14.3


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 3/8] NFS: Move the delegation return down into nfs4_proc_remove()
  2018-03-20 20:43   ` [PATCH 2/8] NFS: Move the delegation return down into nfs4_proc_link() Trond Myklebust
@ 2018-03-20 20:43     ` Trond Myklebust
  2018-03-20 20:43       ` [PATCH 4/8] NFS: Move delegation recall into the NFSv4 callback for rename_setup() Trond Myklebust
  0 siblings, 1 reply; 9+ messages in thread
From: Trond Myklebust @ 2018-03-20 20:43 UTC (permalink / raw)
  To: Anna Schumaker; +Cc: linux-nfs

Move the delegation return out of generic code and down into the
NFSv4 specific unlink code.

Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
---
 fs/nfs/dir.c            |  5 ++---
 fs/nfs/nfs3proc.c       |  6 +++---
 fs/nfs/nfs4proc.c       | 22 ++++++++++++++++++++--
 fs/nfs/proc.c           |  6 +++---
 include/linux/nfs_xdr.h |  2 +-
 5 files changed, 29 insertions(+), 12 deletions(-)

diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index b4549e54007d..eb9d782ed674 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -1798,12 +1798,11 @@ static int nfs_safe_remove(struct dentry *dentry)
 
 	trace_nfs_remove_enter(dir, dentry);
 	if (inode != NULL) {
-		NFS_PROTO(inode)->return_delegation(inode);
-		error = NFS_PROTO(dir)->remove(dir, &dentry->d_name);
+		error = NFS_PROTO(dir)->remove(dir, dentry);
 		if (error == 0)
 			nfs_drop_nlink(inode);
 	} else
-		error = NFS_PROTO(dir)->remove(dir, &dentry->d_name);
+		error = NFS_PROTO(dir)->remove(dir, dentry);
 	if (error == -ENOENT)
 		nfs_dentry_handle_enoent(dentry);
 	trace_nfs_remove_exit(dir, dentry, error);
diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c
index 7327930ad970..f4ead71e4350 100644
--- a/fs/nfs/nfs3proc.c
+++ b/fs/nfs/nfs3proc.c
@@ -383,11 +383,11 @@ nfs3_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
 }
 
 static int
-nfs3_proc_remove(struct inode *dir, const struct qstr *name)
+nfs3_proc_remove(struct inode *dir, struct dentry *dentry)
 {
 	struct nfs_removeargs arg = {
 		.fh = NFS_FH(dir),
-		.name = *name,
+		.name = dentry->d_name,
 	};
 	struct nfs_removeres res;
 	struct rpc_message msg = {
@@ -397,7 +397,7 @@ nfs3_proc_remove(struct inode *dir, const struct qstr *name)
 	};
 	int status = -ENOMEM;
 
-	dprintk("NFS call  remove %s\n", name->name);
+	dprintk("NFS call  remove %pd2\n", dentry);
 	res.dir_attr = nfs_alloc_fattr();
 	if (res.dir_attr == NULL)
 		goto out;
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 8290a04907b0..69a2428eef10 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -4200,10 +4200,28 @@ static int _nfs4_proc_remove(struct inode *dir, const struct qstr *name)
 	return status;
 }
 
-static int nfs4_proc_remove(struct inode *dir, const struct qstr *name)
+static int nfs4_proc_remove(struct inode *dir, struct dentry *dentry)
 {
 	struct nfs4_exception exception = { };
+	struct inode *inode = d_inode(dentry);
 	int err;
+
+	if (inode)
+		nfs4_inode_return_delegation(inode);
+	do {
+		err = _nfs4_proc_remove(dir, &dentry->d_name);
+		trace_nfs4_remove(dir, &dentry->d_name, err);
+		err = nfs4_handle_exception(NFS_SERVER(dir), err,
+				&exception);
+	} while (exception.retry);
+	return err;
+}
+
+static int nfs4_proc_rmdir(struct inode *dir, const struct qstr *name)
+{
+	struct nfs4_exception exception = { };
+	int err;
+
 	do {
 		err = _nfs4_proc_remove(dir, name);
 		trace_nfs4_remove(dir, name, err);
@@ -9596,7 +9614,7 @@ const struct nfs_rpc_ops nfs_v4_clientops = {
 	.link		= nfs4_proc_link,
 	.symlink	= nfs4_proc_symlink,
 	.mkdir		= nfs4_proc_mkdir,
-	.rmdir		= nfs4_proc_remove,
+	.rmdir		= nfs4_proc_rmdir,
 	.readdir	= nfs4_proc_readdir,
 	.mknod		= nfs4_proc_mknod,
 	.statfs		= nfs4_proc_statfs,
diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c
index f7fd9192d4bc..b2e81a110133 100644
--- a/fs/nfs/proc.c
+++ b/fs/nfs/proc.c
@@ -300,11 +300,11 @@ nfs_proc_mknod(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
 }
   
 static int
-nfs_proc_remove(struct inode *dir, const struct qstr *name)
+nfs_proc_remove(struct inode *dir, struct dentry *dentry)
 {
 	struct nfs_removeargs arg = {
 		.fh = NFS_FH(dir),
-		.name = *name,
+		.name = dentry->d_name,
 	};
 	struct rpc_message msg = { 
 		.rpc_proc = &nfs_procedures[NFSPROC_REMOVE],
@@ -312,7 +312,7 @@ nfs_proc_remove(struct inode *dir, const struct qstr *name)
 	};
 	int			status;
 
-	dprintk("NFS call  remove %s\n", name->name);
+	dprintk("NFS call  remove %pd2\n",dentry);
 	status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
 	nfs_mark_for_revalidate(dir);
 
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index 6959968dc36a..3ebf14b3bf0b 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -1590,7 +1590,7 @@ struct nfs_rpc_ops {
 			    unsigned int);
 	int	(*create)  (struct inode *, struct dentry *,
 			    struct iattr *, int);
-	int	(*remove)  (struct inode *, const struct qstr *);
+	int	(*remove)  (struct inode *, struct dentry *);
 	void	(*unlink_setup)  (struct rpc_message *, struct inode *dir);
 	void	(*unlink_rpc_prepare) (struct rpc_task *, struct nfs_unlinkdata *);
 	int	(*unlink_done) (struct rpc_task *, struct inode *);
-- 
2.14.3


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 4/8] NFS: Move delegation recall into the NFSv4 callback for rename_setup()
  2018-03-20 20:43     ` [PATCH 3/8] NFS: Move the delegation return down into nfs4_proc_remove() Trond Myklebust
@ 2018-03-20 20:43       ` Trond Myklebust
  2018-03-20 20:43         ` [PATCH 5/8] NFS: Add a delegation return into nfs4_proc_unlink_setup() Trond Myklebust
  0 siblings, 1 reply; 9+ messages in thread
From: Trond Myklebust @ 2018-03-20 20:43 UTC (permalink / raw)
  To: Anna Schumaker; +Cc: linux-nfs

Move the delegation recall out of the generic code, and into the NFSv4
specific callback.

Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
---
 fs/nfs/dir.c            |  4 ----
 fs/nfs/nfs3proc.c       |  4 +++-
 fs/nfs/nfs4proc.c       | 13 ++++++++++---
 fs/nfs/proc.c           |  4 +++-
 fs/nfs/unlink.c         |  5 +----
 include/linux/nfs_xdr.h |  4 +++-
 6 files changed, 20 insertions(+), 14 deletions(-)

diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index eb9d782ed674..8001f8c7ad0e 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -2020,10 +2020,6 @@ int nfs_rename(struct inode *old_dir, struct dentry *old_dentry,
 		}
 	}
 
-	NFS_PROTO(old_inode)->return_delegation(old_inode);
-	if (new_inode != NULL)
-		NFS_PROTO(new_inode)->return_delegation(new_inode);
-
 	task = nfs_async_rename(old_dir, new_dir, old_dentry, new_dentry, NULL);
 	if (IS_ERR(task)) {
 		error = PTR_ERR(task);
diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c
index f4ead71e4350..08875dc17b52 100644
--- a/fs/nfs/nfs3proc.c
+++ b/fs/nfs/nfs3proc.c
@@ -433,7 +433,9 @@ nfs3_proc_unlink_done(struct rpc_task *task, struct inode *dir)
 }
 
 static void
-nfs3_proc_rename_setup(struct rpc_message *msg, struct inode *dir)
+nfs3_proc_rename_setup(struct rpc_message *msg,
+		struct dentry *old_dentry,
+		struct dentry *new_dentry)
 {
 	msg->rpc_proc = &nfs3_procedures[NFS3PROC_RENAME];
 }
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 69a2428eef10..f7149028efc7 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -4267,14 +4267,21 @@ static int nfs4_proc_unlink_done(struct rpc_task *task, struct inode *dir)
 	return 1;
 }
 
-static void nfs4_proc_rename_setup(struct rpc_message *msg, struct inode *dir)
+static void nfs4_proc_rename_setup(struct rpc_message *msg,
+		struct dentry *old_dentry,
+		struct dentry *new_dentry)
 {
-	struct nfs_server *server = NFS_SERVER(dir);
 	struct nfs_renameargs *arg = msg->rpc_argp;
 	struct nfs_renameres *res = msg->rpc_resp;
+	struct inode *old_inode = d_inode(old_dentry);
+	struct inode *new_inode = d_inode(new_dentry);
 
+	if (old_inode)
+		nfs4_inode_return_delegation(old_inode);
+	if (new_inode)
+		nfs4_inode_return_delegation(new_inode);
 	msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_RENAME];
-	res->server = server;
+	res->server = NFS_SB(old_dentry->d_sb);
 	nfs4_init_sequence(&arg->seq_args, &res->seq_res, 1);
 }
 
diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c
index b2e81a110133..39dc9276b1f6 100644
--- a/fs/nfs/proc.c
+++ b/fs/nfs/proc.c
@@ -338,7 +338,9 @@ static int nfs_proc_unlink_done(struct rpc_task *task, struct inode *dir)
 }
 
 static void
-nfs_proc_rename_setup(struct rpc_message *msg, struct inode *dir)
+nfs_proc_rename_setup(struct rpc_message *msg,
+		struct dentry *old_dentry,
+		struct dentry *new_dentry)
 {
 	msg->rpc_proc = &nfs_procedures[NFSPROC_RENAME];
 }
diff --git a/fs/nfs/unlink.c b/fs/nfs/unlink.c
index 630b4a3c1a93..44f101411422 100644
--- a/fs/nfs/unlink.c
+++ b/fs/nfs/unlink.c
@@ -386,7 +386,7 @@ nfs_async_rename(struct inode *old_dir, struct inode *new_dir,
 
 	nfs_sb_active(old_dir->i_sb);
 
-	NFS_PROTO(data->old_dir)->rename_setup(&msg, old_dir);
+	NFS_PROTO(data->old_dir)->rename_setup(&msg, old_dentry, new_dentry);
 
 	return rpc_run_task(&task_setup_data);
 }
@@ -463,9 +463,6 @@ nfs_sillyrename(struct inode *dir, struct dentry *dentry)
 
 	fileid = NFS_FILEID(d_inode(dentry));
 
-	/* Return delegation in anticipation of the rename */
-	NFS_PROTO(d_inode(dentry))->return_delegation(d_inode(dentry));
-
 	sdentry = NULL;
 	do {
 		int slen;
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index 3ebf14b3bf0b..4b87e2d726b1 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -1594,7 +1594,9 @@ struct nfs_rpc_ops {
 	void	(*unlink_setup)  (struct rpc_message *, struct inode *dir);
 	void	(*unlink_rpc_prepare) (struct rpc_task *, struct nfs_unlinkdata *);
 	int	(*unlink_done) (struct rpc_task *, struct inode *);
-	void	(*rename_setup)  (struct rpc_message *msg, struct inode *dir);
+	void	(*rename_setup)  (struct rpc_message *msg,
+			struct dentry *old_dentry,
+			struct dentry *new_dentry);
 	void	(*rename_rpc_prepare)(struct rpc_task *task, struct nfs_renamedata *);
 	int	(*rename_done) (struct rpc_task *task, struct inode *old_dir, struct inode *new_dir);
 	int	(*link)    (struct inode *, struct inode *, const struct qstr *);
-- 
2.14.3


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 5/8] NFS: Add a delegation return into nfs4_proc_unlink_setup()
  2018-03-20 20:43       ` [PATCH 4/8] NFS: Move delegation recall into the NFSv4 callback for rename_setup() Trond Myklebust
@ 2018-03-20 20:43         ` Trond Myklebust
  2018-03-20 20:43           ` [PATCH 6/8] NFS: Move the delegation return down into _nfs4_do_setattr() Trond Myklebust
  0 siblings, 1 reply; 9+ messages in thread
From: Trond Myklebust @ 2018-03-20 20:43 UTC (permalink / raw)
  To: Anna Schumaker; +Cc: linux-nfs

Ensure that when we do finally delete the file, then we return the
delegation.

Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
---
 fs/nfs/nfs3proc.c       | 2 +-
 fs/nfs/nfs4proc.c       | 9 ++++++---
 fs/nfs/proc.c           | 2 +-
 fs/nfs/unlink.c         | 2 +-
 include/linux/nfs_xdr.h | 2 +-
 5 files changed, 10 insertions(+), 7 deletions(-)

diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c
index 08875dc17b52..ae03307bd8cd 100644
--- a/fs/nfs/nfs3proc.c
+++ b/fs/nfs/nfs3proc.c
@@ -411,7 +411,7 @@ nfs3_proc_remove(struct inode *dir, struct dentry *dentry)
 }
 
 static void
-nfs3_proc_unlink_setup(struct rpc_message *msg, struct inode *dir)
+nfs3_proc_unlink_setup(struct rpc_message *msg, struct dentry *dentry)
 {
 	msg->rpc_proc = &nfs3_procedures[NFS3PROC_REMOVE];
 }
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index f7149028efc7..2953da680bc7 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -4231,17 +4231,20 @@ static int nfs4_proc_rmdir(struct inode *dir, const struct qstr *name)
 	return err;
 }
 
-static void nfs4_proc_unlink_setup(struct rpc_message *msg, struct inode *dir)
+static void nfs4_proc_unlink_setup(struct rpc_message *msg, struct dentry *dentry)
 {
-	struct nfs_server *server = NFS_SERVER(dir);
 	struct nfs_removeargs *args = msg->rpc_argp;
 	struct nfs_removeres *res = msg->rpc_resp;
+	struct inode *inode = d_inode(dentry);
 
-	res->server = server;
+	res->server = NFS_SB(dentry->d_sb);
 	msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_REMOVE];
 	nfs4_init_sequence(&args->seq_args, &res->seq_res, 1);
 
 	nfs_fattr_init(res->dir_attr);
+
+	if (inode)
+		nfs4_inode_return_delegation(inode);
 }
 
 static void nfs4_proc_unlink_rpc_prepare(struct rpc_task *task, struct nfs_unlinkdata *data)
diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c
index 39dc9276b1f6..318b3f34a6d0 100644
--- a/fs/nfs/proc.c
+++ b/fs/nfs/proc.c
@@ -321,7 +321,7 @@ nfs_proc_remove(struct inode *dir, struct dentry *dentry)
 }
 
 static void
-nfs_proc_unlink_setup(struct rpc_message *msg, struct inode *dir)
+nfs_proc_unlink_setup(struct rpc_message *msg, struct dentry *dentry)
 {
 	msg->rpc_proc = &nfs_procedures[NFSPROC_REMOVE];
 }
diff --git a/fs/nfs/unlink.c b/fs/nfs/unlink.c
index 44f101411422..bf54fc9ae135 100644
--- a/fs/nfs/unlink.c
+++ b/fs/nfs/unlink.c
@@ -105,7 +105,7 @@ static void nfs_do_call_unlink(struct nfs_unlinkdata *data)
 	data->args.fh = NFS_FH(dir);
 	nfs_fattr_init(data->res.dir_attr);
 
-	NFS_PROTO(dir)->unlink_setup(&msg, dir);
+	NFS_PROTO(dir)->unlink_setup(&msg, data->dentry);
 
 	task_setup_data.rpc_client = NFS_CLIENT(dir);
 	task = rpc_run_task(&task_setup_data);
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index 4b87e2d726b1..c4ba58b3c0f8 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -1591,7 +1591,7 @@ struct nfs_rpc_ops {
 	int	(*create)  (struct inode *, struct dentry *,
 			    struct iattr *, int);
 	int	(*remove)  (struct inode *, struct dentry *);
-	void	(*unlink_setup)  (struct rpc_message *, struct inode *dir);
+	void	(*unlink_setup)  (struct rpc_message *, struct dentry *);
 	void	(*unlink_rpc_prepare) (struct rpc_task *, struct nfs_unlinkdata *);
 	int	(*unlink_done) (struct rpc_task *, struct inode *);
 	void	(*rename_setup)  (struct rpc_message *msg,
-- 
2.14.3


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 6/8] NFS: Move the delegation return down into _nfs4_do_setattr()
  2018-03-20 20:43         ` [PATCH 5/8] NFS: Add a delegation return into nfs4_proc_unlink_setup() Trond Myklebust
@ 2018-03-20 20:43           ` Trond Myklebust
  2018-03-20 20:43             ` [PATCH 7/8] NFS: Remove the unused return_delegation() callback Trond Myklebust
  0 siblings, 1 reply; 9+ messages in thread
From: Trond Myklebust @ 2018-03-20 20:43 UTC (permalink / raw)
  To: Anna Schumaker; +Cc: linux-nfs

Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
---
 fs/nfs/inode.c    | 5 -----
 fs/nfs/nfs4proc.c | 4 ++++
 2 files changed, 4 insertions(+), 5 deletions(-)

diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 7d893543cf3b..9da00b2e26a1 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -613,11 +613,6 @@ nfs_setattr(struct dentry *dentry, struct iattr *attr)
 		goto out;
 	}
 
-	/*
-	 * Return any delegations if we're going to change ACLs
-	 */
-	if ((attr->ia_valid & (ATTR_MODE|ATTR_UID|ATTR_GID)) != 0)
-		NFS_PROTO(inode)->return_delegation(inode);
 	error = NFS_PROTO(inode)->setattr(dentry, fattr, attr);
 	if (error == 0)
 		error = nfs_refresh_inode(inode, fattr);
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 2953da680bc7..e1550627c4d5 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -3875,6 +3875,10 @@ nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr,
 	if (IS_ERR(label))
 		return PTR_ERR(label);
 
+	/* Return any delegations if we're going to change ACLs */
+	if ((sattr->ia_valid & (ATTR_MODE|ATTR_UID|ATTR_GID)) != 0)
+		nfs4_inode_return_delegation(inode);
+
 	status = nfs4_do_setattr(inode, cred, fattr, sattr, ctx, NULL, label);
 	if (status == 0) {
 		nfs_setattr_update_inode(inode, sattr, fattr);
-- 
2.14.3


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 7/8] NFS: Remove the unused return_delegation() callback
  2018-03-20 20:43           ` [PATCH 6/8] NFS: Move the delegation return down into _nfs4_do_setattr() Trond Myklebust
@ 2018-03-20 20:43             ` Trond Myklebust
  2018-03-20 20:43               ` [PATCH 8/8] NFSv4: Don't return the delegation when not needed by NFSv4.x (x>0) Trond Myklebust
  0 siblings, 1 reply; 9+ messages in thread
From: Trond Myklebust @ 2018-03-20 20:43 UTC (permalink / raw)
  To: Anna Schumaker; +Cc: linux-nfs

Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
---
 fs/nfs/nfs3proc.c       | 7 -------
 fs/nfs/nfs4proc.c       | 1 -
 fs/nfs/proc.c           | 7 -------
 include/linux/nfs_xdr.h | 1 -
 4 files changed, 16 deletions(-)

diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c
index ae03307bd8cd..cc04d988db7c 100644
--- a/fs/nfs/nfs3proc.c
+++ b/fs/nfs/nfs3proc.c
@@ -910,12 +910,6 @@ static int nfs3_have_delegation(struct inode *inode, fmode_t flags)
 	return 0;
 }
 
-static int nfs3_return_delegation(struct inode *inode)
-{
-	nfs_wb_all(inode);
-	return 0;
-}
-
 static const struct inode_operations nfs3_dir_inode_operations = {
 	.create		= nfs_create,
 	.lookup		= nfs_lookup,
@@ -992,7 +986,6 @@ const struct nfs_rpc_ops nfs_v3_clientops = {
 	.clear_acl_cache = forget_all_cached_acls,
 	.close_context	= nfs_close_context,
 	.have_delegation = nfs3_have_delegation,
-	.return_delegation = nfs3_return_delegation,
 	.alloc_client	= nfs_alloc_client,
 	.init_client	= nfs_init_client,
 	.free_client	= nfs_free_client,
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index e1550627c4d5..ef57a0eb5647 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -9649,7 +9649,6 @@ const struct nfs_rpc_ops nfs_v4_clientops = {
 	.close_context  = nfs4_close_context,
 	.open_context	= nfs4_atomic_open,
 	.have_delegation = nfs4_have_delegation,
-	.return_delegation = nfs4_inode_return_delegation,
 	.alloc_client	= nfs4_alloc_client,
 	.init_client	= nfs4_init_client,
 	.free_client	= nfs4_free_client,
diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c
index 318b3f34a6d0..4e93d6308733 100644
--- a/fs/nfs/proc.c
+++ b/fs/nfs/proc.c
@@ -673,12 +673,6 @@ static int nfs_have_delegation(struct inode *inode, fmode_t flags)
 	return 0;
 }
 
-static int nfs_return_delegation(struct inode *inode)
-{
-	nfs_wb_all(inode);
-	return 0;
-}
-
 static const struct inode_operations nfs_dir_inode_operations = {
 	.create		= nfs_create,
 	.lookup		= nfs_lookup,
@@ -743,7 +737,6 @@ const struct nfs_rpc_ops nfs_v2_clientops = {
 	.lock_check_bounds = nfs_lock_check_bounds,
 	.close_context	= nfs_close_context,
 	.have_delegation = nfs_have_delegation,
-	.return_delegation = nfs_return_delegation,
 	.alloc_client	= nfs_alloc_client,
 	.init_client	= nfs_init_client,
 	.free_client	= nfs_free_client,
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index c4ba58b3c0f8..34d28564ecf3 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -1635,7 +1635,6 @@ struct nfs_rpc_ops {
 				struct iattr *iattr,
 				int *);
 	int (*have_delegation)(struct inode *, fmode_t);
-	int (*return_delegation)(struct inode *);
 	struct nfs_client *(*alloc_client) (const struct nfs_client_initdata *);
 	struct nfs_client *(*init_client) (struct nfs_client *,
 				const struct nfs_client_initdata *);
-- 
2.14.3


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 8/8] NFSv4: Don't return the delegation when not needed by NFSv4.x (x>0)
  2018-03-20 20:43             ` [PATCH 7/8] NFS: Remove the unused return_delegation() callback Trond Myklebust
@ 2018-03-20 20:43               ` Trond Myklebust
  0 siblings, 0 replies; 9+ messages in thread
From: Trond Myklebust @ 2018-03-20 20:43 UTC (permalink / raw)
  To: Anna Schumaker; +Cc: linux-nfs

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>
---
 fs/nfs/delegation.c | 17 +++++++++++++++++
 fs/nfs/delegation.h |  1 +
 fs/nfs/nfs4proc.c   | 16 ++++++++++------
 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 @@
 #include <linux/nfs_xdr.h>
 
 #include "nfs4_fs.h"
+#include "nfs4session.h"
 #include "delegation.h"
 #include "internal.h"
 #include "nfs4trace.h"
@@ -547,6 +548,22 @@ int nfs4_inode_return_delegation(struct inode *inode)
 	return err;
 }
 
+/**
+ * nfs4_inode_make_writeable
+ * @inode: pointer to inode
+ *
+ * Make the inode writeable by returning the delegation if necessary
+ *
+ * Returns zero on success, or a negative errno value.
+ */
+int nfs4_inode_make_writeable(struct inode *inode)
+{
+	if (!nfs4_has_session(NFS_SERVER(inode)->nfs_client) ||
+	    !nfs4_check_delegation(inode, FMODE_WRITE))
+		return nfs4_inode_return_delegation(inode);
+	return 0;
+}
+
 static void nfs_mark_return_if_closed_delegation(struct nfs_server *server,
 		struct nfs_delegation *delegation)
 {
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);
 bool nfs4_delegation_flush_on_close(const struct inode *inode);
 void nfs_inode_find_delegation_state_and_recover(struct inode *inode,
 		const nfs4_stateid *stateid);
+int nfs4_inode_make_writeable(struct inode *inode);
 
 #endif
 
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index ef57a0eb5647..b4ebee12fe28 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,
 
 	/* Return any delegations if we're going to change ACLs */
 	if ((sattr->ia_valid & (ATTR_MODE|ATTR_UID|ATTR_GID)) != 0)
-		nfs4_inode_return_delegation(inode);
+		nfs4_inode_make_writeable(inode);
 
 	status = nfs4_do_setattr(inode, cred, fattr, sattr, ctx, NULL, label);
 	if (status == 0) {
@@ -4210,8 +4210,12 @@ static int nfs4_proc_remove(struct inode *dir, struct dentry *dentry)
 	struct inode *inode = d_inode(dentry);
 	int err;
 
-	if (inode)
-		nfs4_inode_return_delegation(inode);
+	if (inode) {
+		if (inode->i_nlink == 1)
+			nfs4_inode_return_delegation(inode);
+		else
+			nfs4_inode_make_writeable(inode);
+	}
 	do {
 		err = _nfs4_proc_remove(dir, &dentry->d_name);
 		trace_nfs4_remove(dir, &dentry->d_name, err);
@@ -4284,7 +4288,7 @@ static void nfs4_proc_rename_setup(struct rpc_message *msg,
 	struct inode *new_inode = d_inode(new_dentry);
 
 	if (old_inode)
-		nfs4_inode_return_delegation(old_inode);
+		nfs4_inode_make_writeable(old_inode);
 	if (new_inode)
 		nfs4_inode_return_delegation(new_inode);
 	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
 	}
 	arg.bitmask = nfs4_bitmask(server, res.label);
 
-	nfs4_inode_return_delegation(inode);
+	nfs4_inode_make_writeable(inode);
 
 	status = nfs4_call_sync(server->client, server, &msg, &arg.seq_args, &res.seq_res, 1);
 	if (!status) {
@@ -5345,7 +5349,7 @@ static int __nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t bufl
 	i = buf_to_pages_noslab(buf, buflen, arg.acl_pages);
 	if (i < 0)
 		return i;
-	nfs4_inode_return_delegation(inode);
+	nfs4_inode_make_writeable(inode);
 	ret = nfs4_call_sync(server->client, server, &msg, &arg.seq_args, &res.seq_res, 1);
 
 	/*
-- 
2.14.3


^ permalink raw reply related	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2018-03-20 20:43 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-03-20 20:43 [PATCH 0/8] Don't return delegations unnecessarily in NFSv4.1 Trond Myklebust
2018-03-20 20:43 ` [PATCH 1/8] NFSv4: Fix nfs4_return_incompatible_delegation Trond Myklebust
2018-03-20 20:43   ` [PATCH 2/8] NFS: Move the delegation return down into nfs4_proc_link() Trond Myklebust
2018-03-20 20:43     ` [PATCH 3/8] NFS: Move the delegation return down into nfs4_proc_remove() Trond Myklebust
2018-03-20 20:43       ` [PATCH 4/8] NFS: Move delegation recall into the NFSv4 callback for rename_setup() Trond Myklebust
2018-03-20 20:43         ` [PATCH 5/8] NFS: Add a delegation return into nfs4_proc_unlink_setup() Trond Myklebust
2018-03-20 20:43           ` [PATCH 6/8] NFS: Move the delegation return down into _nfs4_do_setattr() Trond Myklebust
2018-03-20 20:43             ` [PATCH 7/8] NFS: Remove the unused return_delegation() callback Trond Myklebust
2018-03-20 20:43               ` [PATCH 8/8] NFSv4: Don't return the delegation when not needed by NFSv4.x (x>0) Trond Myklebust

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.