mirror of
https://github.com/torvalds/linux.git
synced 2024-12-27 13:22:23 +00:00
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: Olga Kornievskaia <kolga@netapp.com> Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
This commit is contained in:
parent
c1830a63c7
commit
5b7eb78486
@ -427,6 +427,7 @@ void xprt_release_write(struct rpc_xprt *, struct rpc_task *);
|
||||
#define XPRT_BOUND (4)
|
||||
#define XPRT_BINDING (5)
|
||||
#define XPRT_CLOSING (6)
|
||||
#define XPRT_OFFLINE (7)
|
||||
#define XPRT_CONGESTED (9)
|
||||
#define XPRT_CWND_WAIT (10)
|
||||
#define XPRT_WRITE_SPACE (11)
|
||||
|
@ -68,6 +68,15 @@ rpc_sysfs_xprt_kobj_get_xprt(struct kobject *kobj)
|
||||
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 *
|
||||
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,
|
||||
struct rpc_xprt *xprt = rpc_sysfs_xprt_kobj_get_xprt(kobj);
|
||||
ssize_t ret;
|
||||
int locked, connected, connecting, close_wait, bound, binding,
|
||||
closing, congested, cwnd_wait, write_space;
|
||||
closing, congested, cwnd_wait, write_space, offline;
|
||||
|
||||
if (!xprt)
|
||||
return 0;
|
||||
@ -140,8 +149,9 @@ static ssize_t rpc_sysfs_xprt_state_show(struct kobject *kobj,
|
||||
congested = test_bit(XPRT_CONGESTED, &xprt->state);
|
||||
cwnd_wait = test_bit(XPRT_CWND_WAIT, &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" : "",
|
||||
connected ? "CONNECTED" : "",
|
||||
connecting ? "CONNECTING" : "",
|
||||
@ -151,7 +161,8 @@ static ssize_t rpc_sysfs_xprt_state_show(struct kobject *kobj,
|
||||
closing ? "CLOSING" : "",
|
||||
congested ? "CONGESTED" : "",
|
||||
cwnd_wait ? "CWND_WAIT" : "",
|
||||
write_space ? "WRITE_SPACE" : "");
|
||||
write_space ? "WRITE_SPACE" : "",
|
||||
offline ? "OFFLINE" : "");
|
||||
}
|
||||
|
||||
xprt_put(xprt);
|
||||
@ -233,6 +244,52 @@ out_err:
|
||||
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)
|
||||
{
|
||||
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,
|
||||
0444, rpc_sysfs_xprt_info_show, NULL);
|
||||
|
||||
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[] = {
|
||||
&rpc_sysfs_xprt_dstaddr.attr,
|
||||
@ -466,6 +523,7 @@ void rpc_sysfs_xprt_setup(struct rpc_xprt_switch *xprt_switch,
|
||||
if (rpc_xprt) {
|
||||
xprt->xprt_sysfs = rpc_xprt;
|
||||
rpc_xprt->xprt = xprt;
|
||||
rpc_xprt->xprt_switch = xprt_switch;
|
||||
kobject_uevent(&rpc_xprt->kobject, KOBJ_ADD);
|
||||
}
|
||||
}
|
||||
|
@ -22,6 +22,7 @@ struct rpc_sysfs_xprt_switch {
|
||||
struct rpc_sysfs_xprt {
|
||||
struct kobject kobject;
|
||||
struct rpc_xprt *xprt;
|
||||
struct rpc_xprt_switch *xprt_switch;
|
||||
};
|
||||
|
||||
int rpc_sysfs_init(void);
|
||||
|
@ -65,7 +65,8 @@ static void xprt_switch_remove_xprt_locked(struct rpc_xprt_switch *xps,
|
||||
{
|
||||
if (unlikely(xprt == NULL))
|
||||
return;
|
||||
xps->xps_nactive--;
|
||||
if (!test_bit(XPRT_OFFLINE, &xprt->state))
|
||||
xps->xps_nactive--;
|
||||
xps->xps_nxprts--;
|
||||
if (xps->xps_nxprts == 0)
|
||||
xps->xps_net = NULL;
|
||||
@ -230,7 +231,8 @@ void xprt_iter_default_rewind(struct rpc_xprt_iter *xpi)
|
||||
static
|
||||
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
|
||||
|
Loading…
Reference in New Issue
Block a user