Commit 5b7eb784 authored by Olga Kornievskaia's avatar Olga Kornievskaia Committed by Trond Myklebust

SUNRPC: take a xprt offline using sysfs

Using sysfs's xprt_state attribute, mark a particular transport offline.
It will not be picked during the round-robin selection. It's not allowed
to take the main (1st created transport associated with the rpc_client)
offline. Also bring a transport back online via sysfs by writing "online"
and that would allow for this transport to be picked during the round-
robin selection.
Signed-off-by: default avatarOlga Kornievskaia <kolga@netapp.com>
Signed-off-by: default avatarTrond Myklebust <trond.myklebust@hammerspace.com>
parent c1830a63
...@@ -427,6 +427,7 @@ void xprt_release_write(struct rpc_xprt *, struct rpc_task *); ...@@ -427,6 +427,7 @@ void xprt_release_write(struct rpc_xprt *, struct rpc_task *);
#define XPRT_BOUND (4) #define XPRT_BOUND (4)
#define XPRT_BINDING (5) #define XPRT_BINDING (5)
#define XPRT_CLOSING (6) #define XPRT_CLOSING (6)
#define XPRT_OFFLINE (7)
#define XPRT_CONGESTED (9) #define XPRT_CONGESTED (9)
#define XPRT_CWND_WAIT (10) #define XPRT_CWND_WAIT (10)
#define XPRT_WRITE_SPACE (11) #define XPRT_WRITE_SPACE (11)
......
...@@ -68,6 +68,15 @@ rpc_sysfs_xprt_kobj_get_xprt(struct kobject *kobj) ...@@ -68,6 +68,15 @@ rpc_sysfs_xprt_kobj_get_xprt(struct kobject *kobj)
return xprt_get(x->xprt); return xprt_get(x->xprt);
} }
static inline struct rpc_xprt_switch *
rpc_sysfs_xprt_kobj_get_xprt_switch(struct kobject *kobj)
{
struct rpc_sysfs_xprt *x = container_of(kobj,
struct rpc_sysfs_xprt, kobject);
return xprt_switch_get(x->xprt_switch);
}
static inline struct rpc_xprt_switch * static inline struct rpc_xprt_switch *
rpc_sysfs_xprt_switch_kobj_get_xprt(struct kobject *kobj) rpc_sysfs_xprt_switch_kobj_get_xprt(struct kobject *kobj)
{ {
...@@ -122,7 +131,7 @@ static ssize_t rpc_sysfs_xprt_state_show(struct kobject *kobj, ...@@ -122,7 +131,7 @@ static ssize_t rpc_sysfs_xprt_state_show(struct kobject *kobj,
struct rpc_xprt *xprt = rpc_sysfs_xprt_kobj_get_xprt(kobj); struct rpc_xprt *xprt = rpc_sysfs_xprt_kobj_get_xprt(kobj);
ssize_t ret; ssize_t ret;
int locked, connected, connecting, close_wait, bound, binding, int locked, connected, connecting, close_wait, bound, binding,
closing, congested, cwnd_wait, write_space; closing, congested, cwnd_wait, write_space, offline;
if (!xprt) if (!xprt)
return 0; return 0;
...@@ -140,8 +149,9 @@ static ssize_t rpc_sysfs_xprt_state_show(struct kobject *kobj, ...@@ -140,8 +149,9 @@ static ssize_t rpc_sysfs_xprt_state_show(struct kobject *kobj,
congested = test_bit(XPRT_CONGESTED, &xprt->state); congested = test_bit(XPRT_CONGESTED, &xprt->state);
cwnd_wait = test_bit(XPRT_CWND_WAIT, &xprt->state); cwnd_wait = test_bit(XPRT_CWND_WAIT, &xprt->state);
write_space = test_bit(XPRT_WRITE_SPACE, &xprt->state); write_space = test_bit(XPRT_WRITE_SPACE, &xprt->state);
offline = test_bit(XPRT_OFFLINE, &xprt->state);
ret = sprintf(buf, "state=%s %s %s %s %s %s %s %s %s %s\n", ret = sprintf(buf, "state=%s %s %s %s %s %s %s %s %s %s %s\n",
locked ? "LOCKED" : "", locked ? "LOCKED" : "",
connected ? "CONNECTED" : "", connected ? "CONNECTED" : "",
connecting ? "CONNECTING" : "", connecting ? "CONNECTING" : "",
...@@ -151,7 +161,8 @@ static ssize_t rpc_sysfs_xprt_state_show(struct kobject *kobj, ...@@ -151,7 +161,8 @@ static ssize_t rpc_sysfs_xprt_state_show(struct kobject *kobj,
closing ? "CLOSING" : "", closing ? "CLOSING" : "",
congested ? "CONGESTED" : "", congested ? "CONGESTED" : "",
cwnd_wait ? "CWND_WAIT" : "", cwnd_wait ? "CWND_WAIT" : "",
write_space ? "WRITE_SPACE" : ""); write_space ? "WRITE_SPACE" : "",
offline ? "OFFLINE" : "");
} }
xprt_put(xprt); xprt_put(xprt);
...@@ -233,6 +244,52 @@ static ssize_t rpc_sysfs_xprt_dstaddr_store(struct kobject *kobj, ...@@ -233,6 +244,52 @@ static ssize_t rpc_sysfs_xprt_dstaddr_store(struct kobject *kobj,
goto out; goto out;
} }
static ssize_t rpc_sysfs_xprt_state_change(struct kobject *kobj,
struct kobj_attribute *attr,
const char *buf, size_t count)
{
struct rpc_xprt *xprt = rpc_sysfs_xprt_kobj_get_xprt(kobj);
int offline = 0, online = 0;
struct rpc_xprt_switch *xps = rpc_sysfs_xprt_kobj_get_xprt_switch(kobj);
if (!xprt)
return 0;
if (!strncmp(buf, "offline", 7))
offline = 1;
else if (!strncmp(buf, "online", 6))
online = 1;
else
return -EINVAL;
if (wait_on_bit_lock(&xprt->state, XPRT_LOCKED, TASK_KILLABLE)) {
count = -EINTR;
goto out_put;
}
if (xprt->main) {
count = -EINVAL;
goto release_tasks;
}
if (offline) {
set_bit(XPRT_OFFLINE, &xprt->state);
spin_lock(&xps->xps_lock);
xps->xps_nactive--;
spin_unlock(&xps->xps_lock);
} else if (online) {
clear_bit(XPRT_OFFLINE, &xprt->state);
spin_lock(&xps->xps_lock);
xps->xps_nactive++;
spin_unlock(&xps->xps_lock);
}
release_tasks:
xprt_release_write(xprt, NULL);
out_put:
xprt_put(xprt);
xprt_switch_put(xps);
return count;
}
int rpc_sysfs_init(void) int rpc_sysfs_init(void)
{ {
rpc_sunrpc_kset = kset_create_and_add("sunrpc", NULL, kernel_kobj); rpc_sunrpc_kset = kset_create_and_add("sunrpc", NULL, kernel_kobj);
...@@ -303,7 +360,7 @@ static struct kobj_attribute rpc_sysfs_xprt_info = __ATTR(xprt_info, ...@@ -303,7 +360,7 @@ static struct kobj_attribute rpc_sysfs_xprt_info = __ATTR(xprt_info,
0444, rpc_sysfs_xprt_info_show, NULL); 0444, rpc_sysfs_xprt_info_show, NULL);
static struct kobj_attribute rpc_sysfs_xprt_change_state = __ATTR(xprt_state, static struct kobj_attribute rpc_sysfs_xprt_change_state = __ATTR(xprt_state,
0644, rpc_sysfs_xprt_state_show, NULL); 0644, rpc_sysfs_xprt_state_show, rpc_sysfs_xprt_state_change);
static struct attribute *rpc_sysfs_xprt_attrs[] = { static struct attribute *rpc_sysfs_xprt_attrs[] = {
&rpc_sysfs_xprt_dstaddr.attr, &rpc_sysfs_xprt_dstaddr.attr,
...@@ -466,6 +523,7 @@ void rpc_sysfs_xprt_setup(struct rpc_xprt_switch *xprt_switch, ...@@ -466,6 +523,7 @@ void rpc_sysfs_xprt_setup(struct rpc_xprt_switch *xprt_switch,
if (rpc_xprt) { if (rpc_xprt) {
xprt->xprt_sysfs = rpc_xprt; xprt->xprt_sysfs = rpc_xprt;
rpc_xprt->xprt = xprt; rpc_xprt->xprt = xprt;
rpc_xprt->xprt_switch = xprt_switch;
kobject_uevent(&rpc_xprt->kobject, KOBJ_ADD); kobject_uevent(&rpc_xprt->kobject, KOBJ_ADD);
} }
} }
......
...@@ -22,6 +22,7 @@ struct rpc_sysfs_xprt_switch { ...@@ -22,6 +22,7 @@ struct rpc_sysfs_xprt_switch {
struct rpc_sysfs_xprt { struct rpc_sysfs_xprt {
struct kobject kobject; struct kobject kobject;
struct rpc_xprt *xprt; struct rpc_xprt *xprt;
struct rpc_xprt_switch *xprt_switch;
}; };
int rpc_sysfs_init(void); int rpc_sysfs_init(void);
......
...@@ -65,7 +65,8 @@ static void xprt_switch_remove_xprt_locked(struct rpc_xprt_switch *xps, ...@@ -65,7 +65,8 @@ static void xprt_switch_remove_xprt_locked(struct rpc_xprt_switch *xps,
{ {
if (unlikely(xprt == NULL)) if (unlikely(xprt == NULL))
return; return;
xps->xps_nactive--; if (!test_bit(XPRT_OFFLINE, &xprt->state))
xps->xps_nactive--;
xps->xps_nxprts--; xps->xps_nxprts--;
if (xps->xps_nxprts == 0) if (xps->xps_nxprts == 0)
xps->xps_net = NULL; xps->xps_net = NULL;
...@@ -230,7 +231,8 @@ void xprt_iter_default_rewind(struct rpc_xprt_iter *xpi) ...@@ -230,7 +231,8 @@ void xprt_iter_default_rewind(struct rpc_xprt_iter *xpi)
static static
bool xprt_is_active(const struct rpc_xprt *xprt) bool xprt_is_active(const struct rpc_xprt *xprt)
{ {
return kref_read(&xprt->kref) != 0; return (kref_read(&xprt->kref) != 0 &&
!test_bit(XPRT_OFFLINE, &xprt->state));
} }
static static
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment