@@ -3,6 +3,8 @@
* Copyright (c) 2020 Anna Schumaker <Anna.Schumaker@Netapp.com>
*/
#include <linux/sunrpc/clnt.h>
+#include <linux/sunrpc/addr.h>
+#include <linux/sunrpc/xprtsock.h>
#include <linux/kobject.h>
#include "sysfs.h"
@@ -55,6 +57,37 @@ int rpc_sysfs_init(void)
return 0;
}
+static ssize_t rpc_netns_dstaddr_show(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+{
+ struct rpc_netns_client *c = container_of(kobj,
+ struct rpc_netns_client, kobject);
+ struct rpc_clnt *clnt = c->clnt;
+ struct rpc_xprt *xprt = rcu_dereference(clnt->cl_xprt);
+
+ return rpc_ntop((struct sockaddr *)&xprt->addr, buf, PAGE_SIZE);
+}
+
+static ssize_t rpc_netns_dstaddr_store(struct kobject *kobj,
+ struct kobj_attribute *attr, const char *buf, size_t count)
+{
+ struct rpc_netns_client *c = container_of(kobj,
+ struct rpc_netns_client, kobject);
+ struct rpc_clnt *clnt = c->clnt;
+ struct rpc_xprt *xprt = rcu_dereference(clnt->cl_xprt);
+ struct sockaddr *saddr = (struct sockaddr *)&xprt->addr;
+ int port = rpc_get_port(saddr);
+
+ xprt->addrlen = rpc_pton(xprt->xprt_net, buf, count - 1, saddr, sizeof(*saddr));
+ rpc_set_port(saddr, port);
+
+ kfree(xprt->address_strings[RPC_DISPLAY_ADDR]);
+ xprt->address_strings[RPC_DISPLAY_ADDR] = kstrndup(buf, count - 1, GFP_KERNEL);
+
+ xprt->ops->connect(xprt, NULL);
+ return count;
+}
+
static void rpc_netns_client_release(struct kobject *kobj)
{
struct rpc_netns_client *c;
@@ -68,8 +101,17 @@ static const void *rpc_netns_client_namespace(struct kobject *kobj)
return container_of(kobj, struct rpc_netns_client, kobject)->net;
}
+static struct kobj_attribute rpc_netns_client_dstaddr = __ATTR(dstaddr,
+ 0644, rpc_netns_dstaddr_show, rpc_netns_dstaddr_store);
+
+static struct attribute *rpc_netns_client_attrs[] = {
+ &rpc_netns_client_dstaddr.attr,
+ NULL,
+};
+
static struct kobj_type rpc_netns_client_type = {
.release = rpc_netns_client_release,
+ .default_attrs = rpc_netns_client_attrs,
.sysfs_ops = &kobj_sysfs_ops,
.namespace = rpc_netns_client_namespace,
};
@@ -100,10 +142,15 @@ static struct rpc_netns_client *rpc_netns_client_alloc(struct kobject *parent,
void rpc_netns_sysfs_setup(struct rpc_clnt *clnt, struct net *net)
{
struct rpc_netns_client *rpc_client;
+ struct rpc_xprt *xprt = rcu_dereference(clnt->cl_xprt);
+
+ if (!(xprt->prot & (IPPROTO_TCP | XPRT_TRANSPORT_RDMA)))
+ return;
rpc_client = rpc_netns_client_alloc(rpc_client_kobj, net, clnt->cl_clid);
if (rpc_client) {
clnt->cl_sysfs = rpc_client;
+ rpc_client->clnt = clnt;
kobject_uevent(&rpc_client->kobject, KOBJ_ADD);
}
}
@@ -8,6 +8,7 @@
struct rpc_netns_client {
struct kobject kobject;
struct net *net;
+ struct rpc_clnt *clnt;
};
extern struct kobject *rpc_client_kobj;