Linux-NFS Archive on lore.kernel.org
 help / color / Atom feed
* [PATCH 0/2] Optionally default to cached info when server is down
@ 2020-01-06 20:39 Trond Myklebust
  2020-01-06 20:39 ` [PATCH 1/2] NFS: Trust cached access if we've already revalidated the inode once Trond Myklebust
  0 siblings, 1 reply; 3+ messages in thread
From: Trond Myklebust @ 2020-01-06 20:39 UTC (permalink / raw)
  To: Anna Schumaker; +Cc: linux-nfs

Add a mount option that allows the NFS client to default to using
cached information (attributes, permissions, data, etc) if the NFS
server is down.

Trond Myklebust (2):
  NFS: Trust cached access if we've already revalidated the inode once
  NFS: Add mount option 'softreval'

 fs/nfs/dir.c              |  4 ++--
 fs/nfs/inode.c            |  8 +++++++-
 fs/nfs/nfs3proc.c         |  7 ++++++-
 fs/nfs/nfs4proc.c         | 33 ++++++++++++++++++++++++++-------
 fs/nfs/proc.c             |  7 ++++++-
 fs/nfs/super.c            | 16 ++++++++++++++--
 include/linux/nfs_fs_sb.h |  1 +
 7 files changed, 62 insertions(+), 14 deletions(-)

-- 
2.24.1


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

* [PATCH 1/2] NFS: Trust cached access if we've already revalidated the inode once
  2020-01-06 20:39 [PATCH 0/2] Optionally default to cached info when server is down Trond Myklebust
@ 2020-01-06 20:39 ` Trond Myklebust
  2020-01-06 20:39   ` [PATCH 2/2] NFS: Add mount option 'softreval' Trond Myklebust
  0 siblings, 1 reply; 3+ messages in thread
From: Trond Myklebust @ 2020-01-06 20:39 UTC (permalink / raw)
  To: Anna Schumaker; +Cc: linux-nfs

If we've already revalidated the inode once then don't distrust the
access cache unless the NFS_INO_INVALID_ACCESS flag is actually set.

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

diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index 372c16b3042c..9405eeadc3f3 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -2312,11 +2312,11 @@ static int nfs_access_get_cached(struct inode *inode, const struct cred *cred, s
 		/* Found an entry, is our attribute cache valid? */
 		if (!nfs_check_cache_invalid(inode, NFS_INO_INVALID_ACCESS))
 			break;
+		if (!retry)
+			break;
 		err = -ECHILD;
 		if (!may_block)
 			goto out;
-		if (!retry)
-			goto out_zap;
 		spin_unlock(&inode->i_lock);
 		err = __nfs_revalidate_inode(NFS_SERVER(inode), inode);
 		if (err)
-- 
2.24.1


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

* [PATCH 2/2] NFS: Add mount option 'softreval'
  2020-01-06 20:39 ` [PATCH 1/2] NFS: Trust cached access if we've already revalidated the inode once Trond Myklebust
@ 2020-01-06 20:39   ` Trond Myklebust
  0 siblings, 0 replies; 3+ messages in thread
From: Trond Myklebust @ 2020-01-06 20:39 UTC (permalink / raw)
  To: Anna Schumaker; +Cc: linux-nfs

Add a mount option 'softreval' that allows attribute revalidation 'getattr'
calls to time out, and causes them to fall back to using the cached
attributes.
The use case for this option is for ensuring that we can still (slowly)
traverse paths and use cached information even when the server is down.
Once the server comes back up again, the getattr calls start succeeding,
and the caches will revalidate as usual.

The 'softreval' mount option is automatically enabled if you have
specified 'softerr'.  It can be turned off using the options
'nosoftreval', or 'hard'.

Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
---
 fs/nfs/inode.c            |  8 +++++++-
 fs/nfs/nfs3proc.c         |  7 ++++++-
 fs/nfs/nfs4proc.c         | 33 ++++++++++++++++++++++++++-------
 fs/nfs/proc.c             |  7 ++++++-
 fs/nfs/super.c            | 16 ++++++++++++++--
 include/linux/nfs_fs_sb.h |  1 +
 6 files changed, 60 insertions(+), 12 deletions(-)

diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index b0b4b9f303fd..71dfc9d2fc3d 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -1156,7 +1156,13 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
 		dfprintk(PAGECACHE, "nfs_revalidate_inode: (%s/%Lu) getattr failed, error=%d\n",
 			 inode->i_sb->s_id,
 			 (unsigned long long)NFS_FILEID(inode), status);
-		if (status == -ESTALE) {
+		switch (status) {
+		case -ETIMEDOUT:
+			/* A soft timeout occurred. Use cached information? */
+			if (server->flags & NFS_MOUNT_SOFTREVAL)
+				status = 0;
+			break;
+		case -ESTALE:
 			nfs_zap_caches(inode);
 			if (!S_ISDIR(inode->i_mode))
 				set_bit(NFS_INO_STALE, &NFS_I(inode)->flags);
diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c
index 9eb2f1a503ab..d401a9c2fe31 100644
--- a/fs/nfs/nfs3proc.c
+++ b/fs/nfs/nfs3proc.c
@@ -110,10 +110,15 @@ nfs3_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle,
 		.rpc_resp	= fattr,
 	};
 	int	status;
+	unsigned short task_flags = 0;
+
+	/* Is this is an attribute revalidation, subject to softreval? */
+	if (inode && (server->flags & NFS_MOUNT_SOFTREVAL))
+		task_flags |= RPC_TASK_TIMEOUT;
 
 	dprintk("NFS call  getattr\n");
 	nfs_fattr_init(fattr);
-	status = rpc_call_sync(server->client, &msg, 0);
+	status = rpc_call_sync(server->client, &msg, task_flags);
 	dprintk("NFS reply getattr: %d\n", status);
 	return status;
 }
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 76d37161409a..eda02b821ea8 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -1097,11 +1097,12 @@ static int nfs4_call_sync_custom(struct rpc_task_setup *task_setup)
 	return ret;
 }
 
-static int nfs4_call_sync_sequence(struct rpc_clnt *clnt,
-				   struct nfs_server *server,
-				   struct rpc_message *msg,
-				   struct nfs4_sequence_args *args,
-				   struct nfs4_sequence_res *res)
+static int nfs4_do_call_sync(struct rpc_clnt *clnt,
+			     struct nfs_server *server,
+			     struct rpc_message *msg,
+			     struct nfs4_sequence_args *args,
+			     struct nfs4_sequence_res *res,
+			     unsigned short task_flags)
 {
 	struct nfs_client *clp = server->nfs_client;
 	struct nfs4_call_sync_data data = {
@@ -1113,12 +1114,23 @@ static int nfs4_call_sync_sequence(struct rpc_clnt *clnt,
 		.rpc_client = clnt,
 		.rpc_message = msg,
 		.callback_ops = clp->cl_mvops->call_sync_ops,
-		.callback_data = &data
+		.callback_data = &data,
+		.flags = task_flags,
 	};
 
 	return nfs4_call_sync_custom(&task_setup);
 }
 
+static int nfs4_call_sync_sequence(struct rpc_clnt *clnt,
+				   struct nfs_server *server,
+				   struct rpc_message *msg,
+				   struct nfs4_sequence_args *args,
+				   struct nfs4_sequence_res *res)
+{
+	return nfs4_do_call_sync(clnt, server, msg, args, res, 0);
+}
+
+
 int nfs4_call_sync(struct rpc_clnt *clnt,
 		   struct nfs_server *server,
 		   struct rpc_message *msg,
@@ -4064,11 +4076,18 @@ static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle,
 		.rpc_argp = &args,
 		.rpc_resp = &res,
 	};
+	unsigned short task_flags = 0;
+
+	/* Is this is an attribute revalidation, subject to softreval? */
+	if (inode && (server->flags & NFS_MOUNT_SOFTREVAL))
+		task_flags |= RPC_TASK_TIMEOUT;
 
 	nfs4_bitmap_copy_adjust(bitmask, nfs4_bitmask(server, label), inode);
 
 	nfs_fattr_init(fattr);
-	return nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0);
+	nfs4_init_sequence(&args.seq_args, &res.seq_res, 0, 0);
+	return nfs4_do_call_sync(server->client, server, &msg,
+			&args.seq_args, &res.seq_res, task_flags);
 }
 
 int nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle,
diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c
index 0f7288b94633..488349f25e0f 100644
--- a/fs/nfs/proc.c
+++ b/fs/nfs/proc.c
@@ -108,10 +108,15 @@ nfs_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle,
 		.rpc_resp	= fattr,
 	};
 	int	status;
+	unsigned short task_flags = 0;
+
+	/* Is this is an attribute revalidation, subject to softreval? */
+	if (inode && (server->flags & NFS_MOUNT_SOFTREVAL))
+		task_flags |= RPC_TASK_TIMEOUT;
 
 	dprintk("NFS call  getattr\n");
 	nfs_fattr_init(fattr);
-	status = rpc_call_sync(server->client, &msg, 0);
+	status = rpc_call_sync(server->client, &msg, task_flags);
 	dprintk("NFS reply getattr: %d\n", status);
 	return status;
 }
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index 8d8d04bb9d64..928f22c76b43 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -82,6 +82,7 @@
 enum {
 	/* Mount options that take no arguments */
 	Opt_soft, Opt_softerr, Opt_hard,
+	Opt_softreval, Opt_nosoftreval,
 	Opt_posix, Opt_noposix,
 	Opt_cto, Opt_nocto,
 	Opt_ac, Opt_noac,
@@ -131,6 +132,8 @@ static const match_table_t nfs_mount_option_tokens = {
 	{ Opt_soft, "soft" },
 	{ Opt_softerr, "softerr" },
 	{ Opt_hard, "hard" },
+	{ Opt_softreval, "softreval" },
+	{ Opt_nosoftreval, "nosoftreval" },
 	{ Opt_deprecated, "intr" },
 	{ Opt_deprecated, "nointr" },
 	{ Opt_posix, "posix" },
@@ -635,6 +638,7 @@ static void nfs_show_mount_options(struct seq_file *m, struct nfs_server *nfss,
 	} nfs_info[] = {
 		{ NFS_MOUNT_SOFT, ",soft", "" },
 		{ NFS_MOUNT_SOFTERR, ",softerr", "" },
+		{ NFS_MOUNT_SOFTREVAL, ",softreval", "" },
 		{ NFS_MOUNT_POSIX, ",posix", "" },
 		{ NFS_MOUNT_NOCTO, ",nocto", "" },
 		{ NFS_MOUNT_NOAC, ",noac", "" },
@@ -1263,11 +1267,19 @@ static int nfs_parse_mount_options(char *raw,
 			mnt->flags &= ~NFS_MOUNT_SOFTERR;
 			break;
 		case Opt_softerr:
-			mnt->flags |= NFS_MOUNT_SOFTERR;
+			mnt->flags |= NFS_MOUNT_SOFTERR | NFS_MOUNT_SOFTREVAL;
 			mnt->flags &= ~NFS_MOUNT_SOFT;
 			break;
 		case Opt_hard:
-			mnt->flags &= ~(NFS_MOUNT_SOFT|NFS_MOUNT_SOFTERR);
+			mnt->flags &= ~(NFS_MOUNT_SOFT |
+					NFS_MOUNT_SOFTERR |
+					NFS_MOUNT_SOFTREVAL);
+			break;
+		case Opt_softreval:
+			mnt->flags |= NFS_MOUNT_SOFTREVAL;
+			break;
+		case Opt_nosoftreval:
+			mnt->flags &= ~NFS_MOUNT_SOFTREVAL;
 			break;
 		case Opt_posix:
 			mnt->flags |= NFS_MOUNT_POSIX;
diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h
index c176f705bf98..465fa98258a3 100644
--- a/include/linux/nfs_fs_sb.h
+++ b/include/linux/nfs_fs_sb.h
@@ -152,6 +152,7 @@ struct nfs_server {
 #define NFS_MOUNT_LOCAL_FLOCK		0x100000
 #define NFS_MOUNT_LOCAL_FCNTL		0x200000
 #define NFS_MOUNT_SOFTERR		0x400000
+#define NFS_MOUNT_SOFTREVAL		0x800000
 
 	unsigned int		caps;		/* server capabilities */
 	unsigned int		rsize;		/* read size */
-- 
2.24.1


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

end of thread, back to index

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-01-06 20:39 [PATCH 0/2] Optionally default to cached info when server is down Trond Myklebust
2020-01-06 20:39 ` [PATCH 1/2] NFS: Trust cached access if we've already revalidated the inode once Trond Myklebust
2020-01-06 20:39   ` [PATCH 2/2] NFS: Add mount option 'softreval' Trond Myklebust

Linux-NFS Archive on lore.kernel.org

Archives are clonable:
	git clone --mirror https://lore.kernel.org/linux-nfs/0 linux-nfs/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 linux-nfs linux-nfs/ https://lore.kernel.org/linux-nfs \
		linux-nfs@vger.kernel.org
	public-inbox-index linux-nfs

Example config snippet for mirrors

Newsgroup available over NNTP:
	nntp://nntp.lore.kernel.org/org.kernel.vger.linux-nfs


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git