Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

NFS: Add a mount option to make ENETUNREACH errors fatal

If the NFS client was initially created in a container, and that
container is torn down, there is usually no possibity to go back and
destroy any NFS clients that are hung because their virtual network
devices have been unlinked.

Add a flag that tells the NFS client that in these circumstances, it
should treat ENETDOWN and ENETUNREACH errors as fatal to the NFS client.

The option defaults to being on when the mount happens from inside a net
namespace that is not "init_net".

Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
Reviewed-by: Jeff Layton <jlayton@kernel.org>
Tested-by: Jeff Layton <jlayton@kernel.org>
Acked-by: Chuck Lever <chuck.lever@oracle.com>

+43
+39
fs/nfs/fs_context.c
··· 50 50 Opt_clientaddr, 51 51 Opt_cto, 52 52 Opt_alignwrite, 53 + Opt_fatal_neterrors, 53 54 Opt_fg, 54 55 Opt_fscache, 55 56 Opt_fscache_flag, ··· 96 95 Opt_wsize, 97 96 Opt_write, 98 97 Opt_xprtsec, 98 + }; 99 + 100 + enum { 101 + Opt_fatal_neterrors_default, 102 + Opt_fatal_neterrors_enetunreach, 103 + Opt_fatal_neterrors_none, 104 + }; 105 + 106 + static const struct constant_table nfs_param_enums_fatal_neterrors[] = { 107 + { "default", Opt_fatal_neterrors_default }, 108 + { "ENETDOWN:ENETUNREACH", Opt_fatal_neterrors_enetunreach }, 109 + { "ENETUNREACH:ENETDOWN", Opt_fatal_neterrors_enetunreach }, 110 + { "none", Opt_fatal_neterrors_none }, 111 + {} 99 112 }; 100 113 101 114 enum { ··· 168 153 fsparam_string("clientaddr", Opt_clientaddr), 169 154 fsparam_flag_no("cto", Opt_cto), 170 155 fsparam_flag_no("alignwrite", Opt_alignwrite), 156 + fsparam_enum("fatal_neterrors", Opt_fatal_neterrors, 157 + nfs_param_enums_fatal_neterrors), 171 158 fsparam_flag ("fg", Opt_fg), 172 159 fsparam_flag_no("fsc", Opt_fscache_flag), 173 160 fsparam_string("fsc", Opt_fscache), ··· 912 895 if (result.uint_32 < 1 || result.uint_32 > NFS_MAX_TRANSPORTS) 913 896 goto out_of_bounds; 914 897 ctx->nfs_server.max_connect = result.uint_32; 898 + break; 899 + case Opt_fatal_neterrors: 900 + trace_nfs_mount_assign(param->key, param->string); 901 + switch (result.uint_32) { 902 + case Opt_fatal_neterrors_default: 903 + if (fc->net_ns != &init_net) 904 + ctx->flags |= NFS_MOUNT_NETUNREACH_FATAL; 905 + else 906 + ctx->flags &= ~NFS_MOUNT_NETUNREACH_FATAL; 907 + break; 908 + case Opt_fatal_neterrors_enetunreach: 909 + ctx->flags |= NFS_MOUNT_NETUNREACH_FATAL; 910 + break; 911 + case Opt_fatal_neterrors_none: 912 + ctx->flags &= ~NFS_MOUNT_NETUNREACH_FATAL; 913 + break; 914 + default: 915 + goto out_invalid_value; 916 + } 915 917 break; 916 918 case Opt_lookupcache: 917 919 trace_nfs_mount_assign(param->key, param->string); ··· 1710 1674 ctx->xprtsec.policy = RPC_XPRTSEC_NONE; 1711 1675 ctx->xprtsec.cert_serial = TLS_NO_CERT; 1712 1676 ctx->xprtsec.privkey_serial = TLS_NO_PRIVKEY; 1677 + 1678 + if (fc->net_ns != &init_net) 1679 + ctx->flags |= NFS_MOUNT_NETUNREACH_FATAL; 1713 1680 1714 1681 fc->s_iflags |= SB_I_STABLE_WRITES; 1715 1682 }
+3
fs/nfs/super.c
··· 457 457 { NFS_MOUNT_FORCE_RDIRPLUS, ",rdirplus=force", "" }, 458 458 { NFS_MOUNT_UNSHARED, ",nosharecache", "" }, 459 459 { NFS_MOUNT_NORESVPORT, ",noresvport", "" }, 460 + { NFS_MOUNT_NETUNREACH_FATAL, 461 + ",fatal_neterrors=ENETDOWN:ENETUNREACH", 462 + ",fatal_neterrors=none" }, 460 463 { 0, NULL, NULL } 461 464 }; 462 465 const struct proc_nfs_info *nfs_infop;
+1
include/linux/nfs_fs_sb.h
··· 168 168 #define NFS_MOUNT_SHUTDOWN 0x08000000 169 169 #define NFS_MOUNT_NO_ALIGNWRITE 0x10000000 170 170 #define NFS_MOUNT_FORCE_RDIRPLUS 0x20000000 171 + #define NFS_MOUNT_NETUNREACH_FATAL 0x40000000 171 172 172 173 unsigned int fattr_valid; /* Valid attributes */ 173 174 unsigned int caps; /* server capabilities */