sunrpc: Fix potential race conditions in rpc_sysfs_xprt_state_change()
We need to use test_and_set_bit() when changing xprt state flags to avoid potentially getting xps->xps_nactive out of sync. Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
This commit is contained in:
parent
776d794f28
commit
1a48db3fef
|
@ -309,25 +309,28 @@ static ssize_t rpc_sysfs_xprt_state_change(struct kobject *kobj,
|
|||
goto release_tasks;
|
||||
}
|
||||
if (offline) {
|
||||
set_bit(XPRT_OFFLINE, &xprt->state);
|
||||
spin_lock(&xps->xps_lock);
|
||||
xps->xps_nactive--;
|
||||
spin_unlock(&xps->xps_lock);
|
||||
if (!test_and_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);
|
||||
if (test_and_clear_bit(XPRT_OFFLINE, &xprt->state)) {
|
||||
spin_lock(&xps->xps_lock);
|
||||
xps->xps_nactive++;
|
||||
spin_unlock(&xps->xps_lock);
|
||||
}
|
||||
} else if (remove) {
|
||||
if (test_bit(XPRT_OFFLINE, &xprt->state)) {
|
||||
set_bit(XPRT_REMOVE, &xprt->state);
|
||||
xprt_force_disconnect(xprt);
|
||||
if (test_bit(XPRT_CONNECTED, &xprt->state)) {
|
||||
if (!xprt->sending.qlen &&
|
||||
!xprt->pending.qlen &&
|
||||
!xprt->backlog.qlen &&
|
||||
!atomic_long_read(&xprt->queuelen))
|
||||
rpc_xprt_switch_remove_xprt(xps, xprt);
|
||||
if (!test_and_set_bit(XPRT_REMOVE, &xprt->state)) {
|
||||
xprt_force_disconnect(xprt);
|
||||
if (test_bit(XPRT_CONNECTED, &xprt->state)) {
|
||||
if (!xprt->sending.qlen &&
|
||||
!xprt->pending.qlen &&
|
||||
!xprt->backlog.qlen &&
|
||||
!atomic_long_read(&xprt->queuelen))
|
||||
rpc_xprt_switch_remove_xprt(xps, xprt);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
count = -EINVAL;
|
||||
|
|
Loading…
Reference in New Issue