]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
NFS: Add a mount option "softerr" to allow clients to see ETIMEDOUT errors
authorTrond Myklebust <trondmy@gmail.com>
Sun, 7 Apr 2019 17:59:01 +0000 (13:59 -0400)
committerAnna Schumaker <Anna.Schumaker@Netapp.com>
Thu, 25 Apr 2019 18:18:14 +0000 (14:18 -0400)
Add a mount option that exposes the ETIMEDOUT errors that occur during
soft timeouts to the application. This allows aware applications to
distinguish between server disk IO errors and client timeout errors.

Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
fs/nfs/client.c
fs/nfs/super.c
include/linux/nfs_fs_sb.h

index 90d71fda65cecfb3958cc4391240e2a09bac783e..f74638c5e5b46549bd8b87a8859806fd9e3a9288 100644 (file)
@@ -598,6 +598,8 @@ int nfs_init_server_rpcclient(struct nfs_server *server,
                        sizeof(server->client->cl_timeout_default));
        server->client->cl_timeout = &server->client->cl_timeout_default;
        server->client->cl_softrtry = 0;
+       if (server->flags & NFS_MOUNT_SOFTERR)
+               server->client->cl_softerr = 1;
        if (server->flags & NFS_MOUNT_SOFT)
                server->client->cl_softrtry = 1;
 
index c27ac96a95bd3535bc893493492fdc7681aba1fe..19783e8ba9fbce93f8818e028fb8b3612c7d4eb9 100644 (file)
@@ -78,7 +78,7 @@
 
 enum {
        /* Mount options that take no arguments */
-       Opt_soft, Opt_hard,
+       Opt_soft, Opt_softerr, Opt_hard,
        Opt_posix, Opt_noposix,
        Opt_cto, Opt_nocto,
        Opt_ac, Opt_noac,
@@ -125,6 +125,7 @@ static const match_table_t nfs_mount_option_tokens = {
        { Opt_sloppy, "sloppy" },
 
        { Opt_soft, "soft" },
+       { Opt_softerr, "softerr" },
        { Opt_hard, "hard" },
        { Opt_deprecated, "intr" },
        { Opt_deprecated, "nointr" },
@@ -628,7 +629,8 @@ static void nfs_show_mount_options(struct seq_file *m, struct nfs_server *nfss,
                const char *str;
                const char *nostr;
        } nfs_info[] = {
-               { NFS_MOUNT_SOFT, ",soft", ",hard" },
+               { NFS_MOUNT_SOFT, ",soft", "" },
+               { NFS_MOUNT_SOFTERR, ",softerr", "" },
                { NFS_MOUNT_POSIX, ",posix", "" },
                { NFS_MOUNT_NOCTO, ",nocto", "" },
                { NFS_MOUNT_NOAC, ",noac", "" },
@@ -658,6 +660,8 @@ static void nfs_show_mount_options(struct seq_file *m, struct nfs_server *nfss,
                seq_printf(m, ",acdirmin=%u", nfss->acdirmin/HZ);
        if (nfss->acdirmax != NFS_DEF_ACDIRMAX*HZ || showdefaults)
                seq_printf(m, ",acdirmax=%u", nfss->acdirmax/HZ);
+       if (!(nfss->flags & (NFS_MOUNT_SOFT|NFS_MOUNT_SOFTERR)))
+                       seq_puts(m, ",hard");
        for (nfs_infop = nfs_info; nfs_infop->flag; nfs_infop++) {
                if (nfss->flags & nfs_infop->flag)
                        seq_puts(m, nfs_infop->str);
@@ -1239,10 +1243,15 @@ static int nfs_parse_mount_options(char *raw,
                 */
                case Opt_soft:
                        mnt->flags |= NFS_MOUNT_SOFT;
+                       mnt->flags &= ~NFS_MOUNT_SOFTERR;
                        break;
-               case Opt_hard:
+               case Opt_softerr:
+                       mnt->flags |= NFS_MOUNT_SOFTERR;
                        mnt->flags &= ~NFS_MOUNT_SOFT;
                        break;
+               case Opt_hard:
+                       mnt->flags &= ~(NFS_MOUNT_SOFT|NFS_MOUNT_SOFTERR);
+                       break;
                case Opt_posix:
                        mnt->flags |= NFS_MOUNT_POSIX;
                        break;
index 013ac5b54a09ca9bab6e4bd5d8bd669e55049274..0fbc5d3c5e53658d01e2b160494fcbd72ea91ca2 100644 (file)
@@ -147,6 +147,7 @@ struct nfs_server {
 #define NFS_MOUNT_LEGACY_INTERFACE     0x80000
 #define NFS_MOUNT_LOCAL_FLOCK          0x100000
 #define NFS_MOUNT_LOCAL_FCNTL          0x200000
+#define NFS_MOUNT_SOFTERR              0x400000
 
        unsigned int            caps;           /* server capabilities */
        unsigned int            rsize;          /* read size */