@@ -170,7 +170,6 @@ struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_init)
}
INIT_LIST_HEAD(&clp->cl_superblocks);
- INIT_LIST_HEAD(&clp->cl_local_addrs);
clp->cl_rpcclient = ERR_PTR(-EINVAL);
clp->cl_flags = cl_init->init_flags;
@@ -184,7 +183,6 @@ struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_init)
clp->cl_principal = "*";
clp->cl_xprtsec = cl_init->xprtsec;
- nfs_probe_local_addr(clp);
return clp;
error_cleanup:
@@ -238,19 +236,12 @@ static void pnfs_init_server(struct nfs_server *server)
*/
void nfs_free_client(struct nfs_client *clp)
{
- struct nfs_local_addr *addr, *tmp;
-
nfs_local_disable(clp);
/* -EIO all pending I/O */
if (!IS_ERR(clp->cl_rpcclient))
rpc_shutdown_client(clp->cl_rpcclient);
- list_for_each_entry_safe(addr, tmp, &clp->cl_local_addrs, cl_addrs) {
- list_del(&addr->cl_addrs);
- kfree(addr);
- }
-
put_net(clp->cl_net);
put_nfs_version(clp->cl_nfs_mod);
kfree(clp->cl_hostname);
@@ -348,22 +348,6 @@ ff_layout_init_mirror_ds(struct pnfs_layout_hdr *lo,
return false;
}
-static bool ff_layout_ds_is_local(struct nfs4_pnfs_ds *ds)
-{
- struct nfs_local_addr *addr;
- struct sockaddr *sap;
- struct nfs4_pnfs_ds_addr *da;
-
- list_for_each_entry(da, &ds->ds_addrs, da_node) {
- sap = (struct sockaddr *)&da->da_addr;
- list_for_each_entry(addr, &ds->ds_clp->cl_local_addrs, cl_addrs)
- if (rpc_cmp_addr((struct sockaddr *)&addr->address, sap))
- return true;
- }
-
- return false;
-}
-
/**
* nfs4_ff_layout_prepare_ds - prepare a DS connection for an RPC call
* @lseg: the layout segment we're operating on
@@ -416,10 +400,7 @@ nfs4_ff_layout_prepare_ds(struct pnfs_layout_segment *lseg,
* keep ds_clp even if DS is local, so that if local IO cannot
* proceed somehow, we can fall back to NFS whenever we want.
*/
- if (ff_layout_ds_is_local(ds)) {
- dprintk("%s: found local DS\n", __func__);
- nfs_local_enable(ds->ds_clp);
- }
+ nfs_local_probe(ds->ds_clp);
max_payload =
nfs_block_size(rpc_max_payload(ds->ds_clp->cl_rpcclient),
NULL);
@@ -204,12 +204,6 @@ struct nfs_mount_request {
struct net *net;
};
-struct nfs_local_addr {
- struct list_head cl_addrs;
- struct sockaddr_storage address;
- size_t addrlen;
-};
-
extern int nfs_mount(struct nfs_mount_request *info, int timeo, int retrans);
extern void nfs_umount(const struct nfs_mount_request *info);
@@ -475,7 +469,6 @@ extern int nfs_local_doio(struct nfs_client *, struct file *,
extern int nfs_local_commit(struct nfs_client *, struct file *,
struct nfs_commit_data *,
const struct rpc_call_ops *, int);
-extern void nfs_probe_local_addr(struct nfs_client *clnt);
extern bool nfs_server_is_local(const struct nfs_client *clp);
/* super.c */
@@ -20,8 +20,6 @@
#include <linux/nfs_fs.h>
#include <linux/nfs_xdr.h>
-#include <uapi/linux/if_arp.h>
-
#include "internal.h"
#include "pnfs.h"
#include "nfstrace.h"
@@ -216,7 +214,6 @@ nfs_local_enable(struct nfs_client *clp)
trace_nfs_local_enable(clp);
}
}
-EXPORT_SYMBOL_GPL(nfs_local_enable);
/*
* nfs_local_disable - disable local i/o for an nfs_client
@@ -236,50 +233,12 @@ nfs_local_disable(struct nfs_client *clp)
void
nfs_local_probe(struct nfs_client *clp)
{
- struct sockaddr_in *sin;
- struct sockaddr_in6 *sin6;
- struct nfs_local_addr *addr;
- struct sockaddr *sap;
bool enable = false;
- switch (clp->cl_addr.ss_family) {
- case AF_INET:
- sin = (struct sockaddr_in *)&clp->cl_addr;
- if (ipv4_is_loopback(sin->sin_addr.s_addr)) {
- dprintk("%s: detected IPv4 loopback address\n",
- __func__);
- enable = true;
- }
- break;
- case AF_INET6:
- sin6 = (struct sockaddr_in6 *)&clp->cl_addr;
- if (memcmp(&sin6->sin6_addr, &in6addr_loopback,
- sizeof(struct in6_addr)) == 0) {
- dprintk("%s: detected IPv6 loopback address\n",
- __func__);
- enable = true;
- }
- break;
- default:
- break;
- }
-
- if (enable)
- goto out;
-
- list_for_each_entry(addr, &clp->cl_local_addrs, cl_addrs) {
- sap = (struct sockaddr *)&addr->address;
- if (rpc_cmp_addr((struct sockaddr *)&clp->cl_addr, sap)) {
- dprintk("%s: detected local server.\n", __func__);
- enable = true;
- break;
- }
- }
-
-out:
if (enable)
nfs_local_enable(clp);
}
+EXPORT_SYMBOL_GPL(nfs_local_probe);
/*
* nfs_local_open_fh - open a local filehandle
@@ -880,105 +839,3 @@ nfs_local_commit(struct nfs_client *clp, struct file *filp,
nfs_local_fsync_ctx_put(ctx);
return 0;
}
-
-static int
-nfs_client_add_addr(struct nfs_client *clnt, char *buf, gfp_t flags)
-{
- struct nfs_local_addr *addr;
- struct sockaddr *sap;
-
- dprintk("%s: adding new local IP %s\n", __func__, buf);
- addr = kmalloc(sizeof(*addr), flags);
- if (!addr) {
- printk(KERN_WARNING "NFS: cannot alloc new addr\n");
- return -ENOMEM;
- }
- sap = (struct sockaddr *)&addr->address;
- addr->addrlen = rpc_pton(clnt->cl_net, buf, strlen(buf),
- sap, sizeof(addr->address));
- if (!addr->addrlen) {
- printk(KERN_WARNING "NFS: cannot parse new addr %s\n",
- buf);
- kfree(addr);
- return -EINVAL;
- }
- list_add(&addr->cl_addrs, &clnt->cl_local_addrs);
-
- return 0;
-}
-
-static int
-nfs_client_add_v4_addr(struct nfs_client *clnt, struct in_device *indev,
- char *buf, size_t buflen)
-{
- struct in_ifaddr *ifa;
- int ret;
-
- in_dev_for_each_ifa_rtnl(ifa, indev) {
- snprintf(buf, buflen, "%pI4", &ifa->ifa_local);
- ret = nfs_client_add_addr(clnt, buf, GFP_KERNEL);
- if (ret < 0)
- return ret;
- }
-
- return 0;
-}
-
-#if IS_ENABLED(CONFIG_IPV6)
-static int
-nfs_client_add_v6_addr(struct nfs_client *clnt, struct inet6_dev *in6dev,
- char *buf, size_t buflen)
-{
- struct inet6_ifaddr *ifp;
- int ret = 0;
-
- read_lock_bh(&in6dev->lock);
- list_for_each_entry(ifp, &in6dev->addr_list, if_list) {
- rpc_ntop6_addr_noscopeid(&ifp->addr, buf, buflen);
- ret = nfs_client_add_addr(clnt, buf, GFP_ATOMIC);
- if (ret < 0)
- goto out;
- }
-out:
- read_unlock_bh(&in6dev->lock);
- return ret;
-}
-#else /* CONFIG_IPV6 */
-static int
-nfs_client_add_v6_addr(struct nfs_client *clnt, struct inet6_dev *in6dev,
- char *buf, size_t buflen)
-{
- return 0;
-}
-#endif
-
-/* Find out all local IP addresses. Ignore errors
- * because local IO can be optional.
- */
-void
-nfs_probe_local_addr(struct nfs_client *clnt)
-{
- struct net_device *dev;
- struct in_device *indev;
- struct inet6_dev *in6dev;
- char buf[INET6_ADDRSTRLEN + IPV6_SCOPE_ID_LEN];
- size_t buflen = sizeof(buf);
-
- rtnl_lock();
-
- for_each_netdev(clnt->cl_net, dev) {
- if (dev->type == ARPHRD_LOOPBACK ||
- !(dev->flags & IFF_UP))
- continue;
- indev = __in_dev_get_rtnl(dev);
- if (indev &&
- nfs_client_add_v4_addr(clnt, indev, buf, buflen) < 0)
- break;
- in6dev = __in6_dev_get(dev);
- if (in6dev &&
- nfs_client_add_v6_addr(clnt, in6dev, buf, buflen) < 0)
- break;
- }
-
- rtnl_unlock();
-}
@@ -56,7 +56,6 @@ struct nfs_client {
char * cl_acceptor; /* GSSAPI acceptor name */
struct list_head cl_share_link; /* link in global client list */
struct list_head cl_superblocks; /* List of nfs_server structs */
- struct list_head cl_local_addrs; /* List of local addresses */
struct rpc_clnt * cl_rpcclient;
const struct nfs_rpc_ops *rpc_ops; /* NFS protocol vector */
@@ -68,9 +68,6 @@ static inline bool __rpc_copy_addr4(struct sockaddr *dst,
}
#if IS_ENABLED(CONFIG_IPV6)
-extern size_t rpc_ntop6_addr_noscopeid(const struct in6_addr *addr,
- char *buf, const int buflen);
-
static inline bool rpc_cmp_addr6(const struct sockaddr *sap1,
const struct sockaddr *sap2)
{
@@ -97,12 +94,6 @@ static inline bool __rpc_copy_addr6(struct sockaddr *dst,
return true;
}
#else /* !(IS_ENABLED(CONFIG_IPV6) */
-static size_t rpc_ntop6_addr_noscopeid(const struct in6_addr *addr,
- char *buf, const int buflen)
-{
- return 0;
-}
-
static inline bool rpc_cmp_addr6(const struct sockaddr *sap1,
const struct sockaddr *sap2)
{
@@ -25,9 +25,12 @@
#if IS_ENABLED(CONFIG_IPV6)
-size_t rpc_ntop6_addr_noscopeid(const struct in6_addr *addr,
- char *buf, const int buflen)
+static size_t rpc_ntop6_noscopeid(const struct sockaddr *sap,
+ char *buf, const int buflen)
{
+ const struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sap;
+ const struct in6_addr *addr = &sin6->sin6_addr;
+
/*
* RFC 4291, Section 2.2.2
*
@@ -52,23 +55,13 @@ size_t rpc_ntop6_addr_noscopeid(const struct in6_addr *addr,
*/
if (ipv6_addr_v4mapped(addr))
return snprintf(buf, buflen, "::ffff:%pI4",
- &addr->s6_addr32[3]);
+ &addr->s6_addr32[3]);
/*
* RFC 4291, Section 2.2.1
*/
return snprintf(buf, buflen, "%pI6c", addr);
}
-EXPORT_SYMBOL_GPL(rpc_ntop6_addr_noscopeid);
-
-static size_t rpc_ntop6_noscopeid(const struct sockaddr *sap,
- char *buf, const int buflen)
-{
- const struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sap;
- const struct in6_addr *addr = &sin6->sin6_addr;
-
- return rpc_ntop6_addr_noscopeid(addr, buf, buflen);
-}
static size_t rpc_ntop6(const struct sockaddr *sap,
char *buf, const size_t buflen)
Prepares for determining localio via client and server handshake. The primary reason to avoid the current approach of probing all local network interfaces for the client (during nfs_alloc_client) to use as the basis for _inferring_ that client's server is local (in nfs_local_probe) is: matching IP addresses is brittle, especially so when you have network namespaces (i.e. containers), or when you play games with NAT or iptables. This commit also reverts an earlier commit ("sunrpc: add and export rpc_ntop6_addr_noscopeid") which was only needed/useful in the context of localio's sockaddr based matching. Signed-off-by: Mike Snitzer <snitzer@kernel.org> --- fs/nfs/client.c | 9 -- fs/nfs/flexfilelayout/flexfilelayoutdev.c | 21 +--- fs/nfs/internal.h | 7 -- fs/nfs/localio.c | 145 +--------------------- include/linux/nfs_fs_sb.h | 1 - include/linux/sunrpc/addr.h | 9 -- net/sunrpc/addr.c | 19 +-- 7 files changed, 8 insertions(+), 203 deletions(-)