diff options
Diffstat (limited to 'net/sunrpc/xprt.c')
-rw-r--r-- | net/sunrpc/xprt.c | 42 |
1 files changed, 27 insertions, 15 deletions
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c index 37edea6fa92d..216a1385718a 100644 --- a/net/sunrpc/xprt.c +++ b/net/sunrpc/xprt.c | |||
@@ -48,6 +48,7 @@ | |||
48 | #include <linux/sunrpc/clnt.h> | 48 | #include <linux/sunrpc/clnt.h> |
49 | #include <linux/sunrpc/metrics.h> | 49 | #include <linux/sunrpc/metrics.h> |
50 | #include <linux/sunrpc/bc_xprt.h> | 50 | #include <linux/sunrpc/bc_xprt.h> |
51 | #include <linux/rcupdate.h> | ||
51 | 52 | ||
52 | #include <trace/events/sunrpc.h> | 53 | #include <trace/events/sunrpc.h> |
53 | 54 | ||
@@ -1166,7 +1167,7 @@ void xprt_free(struct rpc_xprt *xprt) | |||
1166 | { | 1167 | { |
1167 | put_net(xprt->xprt_net); | 1168 | put_net(xprt->xprt_net); |
1168 | xprt_free_all_slots(xprt); | 1169 | xprt_free_all_slots(xprt); |
1169 | kfree(xprt); | 1170 | kfree_rcu(xprt, rcu); |
1170 | } | 1171 | } |
1171 | EXPORT_SYMBOL_GPL(xprt_free); | 1172 | EXPORT_SYMBOL_GPL(xprt_free); |
1172 | 1173 | ||
@@ -1180,7 +1181,7 @@ EXPORT_SYMBOL_GPL(xprt_free); | |||
1180 | */ | 1181 | */ |
1181 | void xprt_reserve(struct rpc_task *task) | 1182 | void xprt_reserve(struct rpc_task *task) |
1182 | { | 1183 | { |
1183 | struct rpc_xprt *xprt; | 1184 | struct rpc_xprt *xprt = task->tk_xprt; |
1184 | 1185 | ||
1185 | task->tk_status = 0; | 1186 | task->tk_status = 0; |
1186 | if (task->tk_rqstp != NULL) | 1187 | if (task->tk_rqstp != NULL) |
@@ -1188,11 +1189,8 @@ void xprt_reserve(struct rpc_task *task) | |||
1188 | 1189 | ||
1189 | task->tk_timeout = 0; | 1190 | task->tk_timeout = 0; |
1190 | task->tk_status = -EAGAIN; | 1191 | task->tk_status = -EAGAIN; |
1191 | rcu_read_lock(); | ||
1192 | xprt = rcu_dereference(task->tk_client->cl_xprt); | ||
1193 | if (!xprt_throttle_congested(xprt, task)) | 1192 | if (!xprt_throttle_congested(xprt, task)) |
1194 | xprt->ops->alloc_slot(xprt, task); | 1193 | xprt->ops->alloc_slot(xprt, task); |
1195 | rcu_read_unlock(); | ||
1196 | } | 1194 | } |
1197 | 1195 | ||
1198 | /** | 1196 | /** |
@@ -1206,7 +1204,7 @@ void xprt_reserve(struct rpc_task *task) | |||
1206 | */ | 1204 | */ |
1207 | void xprt_retry_reserve(struct rpc_task *task) | 1205 | void xprt_retry_reserve(struct rpc_task *task) |
1208 | { | 1206 | { |
1209 | struct rpc_xprt *xprt; | 1207 | struct rpc_xprt *xprt = task->tk_xprt; |
1210 | 1208 | ||
1211 | task->tk_status = 0; | 1209 | task->tk_status = 0; |
1212 | if (task->tk_rqstp != NULL) | 1210 | if (task->tk_rqstp != NULL) |
@@ -1214,10 +1212,7 @@ void xprt_retry_reserve(struct rpc_task *task) | |||
1214 | 1212 | ||
1215 | task->tk_timeout = 0; | 1213 | task->tk_timeout = 0; |
1216 | task->tk_status = -EAGAIN; | 1214 | task->tk_status = -EAGAIN; |
1217 | rcu_read_lock(); | ||
1218 | xprt = rcu_dereference(task->tk_client->cl_xprt); | ||
1219 | xprt->ops->alloc_slot(xprt, task); | 1215 | xprt->ops->alloc_slot(xprt, task); |
1220 | rcu_read_unlock(); | ||
1221 | } | 1216 | } |
1222 | 1217 | ||
1223 | static inline __be32 xprt_alloc_xid(struct rpc_xprt *xprt) | 1218 | static inline __be32 xprt_alloc_xid(struct rpc_xprt *xprt) |
@@ -1264,11 +1259,9 @@ void xprt_release(struct rpc_task *task) | |||
1264 | 1259 | ||
1265 | if (req == NULL) { | 1260 | if (req == NULL) { |
1266 | if (task->tk_client) { | 1261 | if (task->tk_client) { |
1267 | rcu_read_lock(); | 1262 | xprt = task->tk_xprt; |
1268 | xprt = rcu_dereference(task->tk_client->cl_xprt); | ||
1269 | if (xprt->snd_task == task) | 1263 | if (xprt->snd_task == task) |
1270 | xprt_release_write(xprt, task); | 1264 | xprt_release_write(xprt, task); |
1271 | rcu_read_unlock(); | ||
1272 | } | 1265 | } |
1273 | return; | 1266 | return; |
1274 | } | 1267 | } |
@@ -1307,7 +1300,7 @@ void xprt_release(struct rpc_task *task) | |||
1307 | 1300 | ||
1308 | static void xprt_init(struct rpc_xprt *xprt, struct net *net) | 1301 | static void xprt_init(struct rpc_xprt *xprt, struct net *net) |
1309 | { | 1302 | { |
1310 | atomic_set(&xprt->count, 1); | 1303 | kref_init(&xprt->kref); |
1311 | 1304 | ||
1312 | spin_lock_init(&xprt->transport_lock); | 1305 | spin_lock_init(&xprt->transport_lock); |
1313 | spin_lock_init(&xprt->reserve_lock); | 1306 | spin_lock_init(&xprt->reserve_lock); |
@@ -1318,6 +1311,7 @@ static void xprt_init(struct rpc_xprt *xprt, struct net *net) | |||
1318 | spin_lock_init(&xprt->bc_pa_lock); | 1311 | spin_lock_init(&xprt->bc_pa_lock); |
1319 | INIT_LIST_HEAD(&xprt->bc_pa_list); | 1312 | INIT_LIST_HEAD(&xprt->bc_pa_list); |
1320 | #endif /* CONFIG_SUNRPC_BACKCHANNEL */ | 1313 | #endif /* CONFIG_SUNRPC_BACKCHANNEL */ |
1314 | INIT_LIST_HEAD(&xprt->xprt_switch); | ||
1321 | 1315 | ||
1322 | xprt->last_used = jiffies; | 1316 | xprt->last_used = jiffies; |
1323 | xprt->cwnd = RPC_INITCWND; | 1317 | xprt->cwnd = RPC_INITCWND; |
@@ -1415,6 +1409,24 @@ static void xprt_destroy(struct rpc_xprt *xprt) | |||
1415 | xprt->ops->destroy(xprt); | 1409 | xprt->ops->destroy(xprt); |
1416 | } | 1410 | } |
1417 | 1411 | ||
1412 | static void xprt_destroy_kref(struct kref *kref) | ||
1413 | { | ||
1414 | xprt_destroy(container_of(kref, struct rpc_xprt, kref)); | ||
1415 | } | ||
1416 | |||
1417 | /** | ||
1418 | * xprt_get - return a reference to an RPC transport. | ||
1419 | * @xprt: pointer to the transport | ||
1420 | * | ||
1421 | */ | ||
1422 | struct rpc_xprt *xprt_get(struct rpc_xprt *xprt) | ||
1423 | { | ||
1424 | if (xprt != NULL && kref_get_unless_zero(&xprt->kref)) | ||
1425 | return xprt; | ||
1426 | return NULL; | ||
1427 | } | ||
1428 | EXPORT_SYMBOL_GPL(xprt_get); | ||
1429 | |||
1418 | /** | 1430 | /** |
1419 | * xprt_put - release a reference to an RPC transport. | 1431 | * xprt_put - release a reference to an RPC transport. |
1420 | * @xprt: pointer to the transport | 1432 | * @xprt: pointer to the transport |
@@ -1422,7 +1434,7 @@ static void xprt_destroy(struct rpc_xprt *xprt) | |||
1422 | */ | 1434 | */ |
1423 | void xprt_put(struct rpc_xprt *xprt) | 1435 | void xprt_put(struct rpc_xprt *xprt) |
1424 | { | 1436 | { |
1425 | if (atomic_dec_and_test(&xprt->count)) | 1437 | if (xprt != NULL) |
1426 | xprt_destroy(xprt); | 1438 | kref_put(&xprt->kref, xprt_destroy_kref); |
1427 | } | 1439 | } |
1428 | EXPORT_SYMBOL_GPL(xprt_put); | 1440 | EXPORT_SYMBOL_GPL(xprt_put); |