diff options
-rw-r--r-- | include/linux/sunrpc/xprt.h | 2 | ||||
-rw-r--r-- | net/sunrpc/xprt.c | 64 |
2 files changed, 37 insertions, 29 deletions
diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h index a876882fb923..05047250f218 100644 --- a/include/linux/sunrpc/xprt.h +++ b/include/linux/sunrpc/xprt.h | |||
@@ -168,7 +168,6 @@ struct rpc_xprt { | |||
168 | struct rpc_wait_queue pending; /* requests in flight */ | 168 | struct rpc_wait_queue pending; /* requests in flight */ |
169 | struct rpc_wait_queue backlog; /* waiting for slot */ | 169 | struct rpc_wait_queue backlog; /* waiting for slot */ |
170 | struct list_head free; /* free slots */ | 170 | struct list_head free; /* free slots */ |
171 | struct rpc_rqst * slot; /* slot table storage */ | ||
172 | unsigned int max_reqs; /* total slots */ | 171 | unsigned int max_reqs; /* total slots */ |
173 | unsigned long state; /* transport state */ | 172 | unsigned long state; /* transport state */ |
174 | unsigned char shutdown : 1, /* being shut down */ | 173 | unsigned char shutdown : 1, /* being shut down */ |
@@ -321,7 +320,6 @@ void xprt_conditional_disconnect(struct rpc_xprt *xprt, unsigned int cookie); | |||
321 | #define XPRT_CLOSING (6) | 320 | #define XPRT_CLOSING (6) |
322 | #define XPRT_CONNECTION_ABORT (7) | 321 | #define XPRT_CONNECTION_ABORT (7) |
323 | #define XPRT_CONNECTION_CLOSE (8) | 322 | #define XPRT_CONNECTION_CLOSE (8) |
324 | #define XPRT_INITIALIZED (9) | ||
325 | 323 | ||
326 | static inline void xprt_set_connected(struct rpc_xprt *xprt) | 324 | static inline void xprt_set_connected(struct rpc_xprt *xprt) |
327 | { | 325 | { |
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c index efb8dc5ab81b..ea7b3c16cddd 100644 --- a/net/sunrpc/xprt.c +++ b/net/sunrpc/xprt.c | |||
@@ -62,6 +62,7 @@ | |||
62 | /* | 62 | /* |
63 | * Local functions | 63 | * Local functions |
64 | */ | 64 | */ |
65 | static void xprt_init(struct rpc_xprt *xprt, struct net *net); | ||
65 | static void xprt_request_init(struct rpc_task *, struct rpc_xprt *); | 66 | static void xprt_request_init(struct rpc_task *, struct rpc_xprt *); |
66 | static void xprt_connect_status(struct rpc_task *task); | 67 | static void xprt_connect_status(struct rpc_task *task); |
67 | static int __xprt_get_cong(struct rpc_xprt *, struct rpc_task *); | 68 | static int __xprt_get_cong(struct rpc_xprt *, struct rpc_task *); |
@@ -961,25 +962,42 @@ static void xprt_free_slot(struct rpc_xprt *xprt, struct rpc_rqst *req) | |||
961 | spin_unlock(&xprt->reserve_lock); | 962 | spin_unlock(&xprt->reserve_lock); |
962 | } | 963 | } |
963 | 964 | ||
964 | struct rpc_xprt *xprt_alloc(struct net *net, int size, int max_req) | 965 | static void xprt_free_all_slots(struct rpc_xprt *xprt) |
966 | { | ||
967 | struct rpc_rqst *req; | ||
968 | while (!list_empty(&xprt->free)) { | ||
969 | req = list_first_entry(&xprt->free, struct rpc_rqst, rq_list); | ||
970 | list_del(&req->rq_list); | ||
971 | kfree(req); | ||
972 | } | ||
973 | } | ||
974 | |||
975 | struct rpc_xprt *xprt_alloc(struct net *net, int size, int num_prealloc) | ||
965 | { | 976 | { |
966 | struct rpc_xprt *xprt; | 977 | struct rpc_xprt *xprt; |
978 | struct rpc_rqst *req; | ||
979 | int i; | ||
967 | 980 | ||
968 | xprt = kzalloc(size, GFP_KERNEL); | 981 | xprt = kzalloc(size, GFP_KERNEL); |
969 | if (xprt == NULL) | 982 | if (xprt == NULL) |
970 | goto out; | 983 | goto out; |
971 | atomic_set(&xprt->count, 1); | ||
972 | 984 | ||
973 | xprt->max_reqs = max_req; | 985 | xprt_init(xprt, net); |
974 | xprt->slot = kcalloc(max_req, sizeof(struct rpc_rqst), GFP_KERNEL); | 986 | |
975 | if (xprt->slot == NULL) | 987 | for (i = 0; i < num_prealloc; i++) { |
988 | req = kzalloc(sizeof(struct rpc_rqst), GFP_KERNEL); | ||
989 | if (!req) | ||
990 | break; | ||
991 | list_add(&req->rq_list, &xprt->free); | ||
992 | } | ||
993 | if (i < num_prealloc) | ||
976 | goto out_free; | 994 | goto out_free; |
995 | xprt->max_reqs = num_prealloc; | ||
977 | 996 | ||
978 | xprt->xprt_net = get_net(net); | ||
979 | return xprt; | 997 | return xprt; |
980 | 998 | ||
981 | out_free: | 999 | out_free: |
982 | kfree(xprt); | 1000 | xprt_free(xprt); |
983 | out: | 1001 | out: |
984 | return NULL; | 1002 | return NULL; |
985 | } | 1003 | } |
@@ -988,7 +1006,7 @@ EXPORT_SYMBOL_GPL(xprt_alloc); | |||
988 | void xprt_free(struct rpc_xprt *xprt) | 1006 | void xprt_free(struct rpc_xprt *xprt) |
989 | { | 1007 | { |
990 | put_net(xprt->xprt_net); | 1008 | put_net(xprt->xprt_net); |
991 | kfree(xprt->slot); | 1009 | xprt_free_all_slots(xprt); |
992 | kfree(xprt); | 1010 | kfree(xprt); |
993 | } | 1011 | } |
994 | EXPORT_SYMBOL_GPL(xprt_free); | 1012 | EXPORT_SYMBOL_GPL(xprt_free); |
@@ -1091,9 +1109,9 @@ void xprt_release(struct rpc_task *task) | |||
1091 | xprt_free_bc_request(req); | 1109 | xprt_free_bc_request(req); |
1092 | } | 1110 | } |
1093 | 1111 | ||
1094 | static void xprt_init(struct rpc_xprt *xprt) | 1112 | static void xprt_init(struct rpc_xprt *xprt, struct net *net) |
1095 | { | 1113 | { |
1096 | struct rpc_rqst *req; | 1114 | atomic_set(&xprt->count, 1); |
1097 | 1115 | ||
1098 | spin_lock_init(&xprt->transport_lock); | 1116 | spin_lock_init(&xprt->transport_lock); |
1099 | spin_lock_init(&xprt->reserve_lock); | 1117 | spin_lock_init(&xprt->reserve_lock); |
@@ -1105,12 +1123,6 @@ static void xprt_init(struct rpc_xprt *xprt) | |||
1105 | INIT_LIST_HEAD(&xprt->bc_pa_list); | 1123 | INIT_LIST_HEAD(&xprt->bc_pa_list); |
1106 | #endif /* CONFIG_SUNRPC_BACKCHANNEL */ | 1124 | #endif /* CONFIG_SUNRPC_BACKCHANNEL */ |
1107 | 1125 | ||
1108 | INIT_WORK(&xprt->task_cleanup, xprt_autoclose); | ||
1109 | if (xprt_has_timer(xprt)) | ||
1110 | setup_timer(&xprt->timer, xprt_init_autodisconnect, | ||
1111 | (unsigned long)xprt); | ||
1112 | else | ||
1113 | init_timer(&xprt->timer); | ||
1114 | xprt->last_used = jiffies; | 1126 | xprt->last_used = jiffies; |
1115 | xprt->cwnd = RPC_INITCWND; | 1127 | xprt->cwnd = RPC_INITCWND; |
1116 | xprt->bind_index = 0; | 1128 | xprt->bind_index = 0; |
@@ -1121,12 +1133,9 @@ static void xprt_init(struct rpc_xprt *xprt) | |||
1121 | rpc_init_wait_queue(&xprt->resend, "xprt_resend"); | 1133 | rpc_init_wait_queue(&xprt->resend, "xprt_resend"); |
1122 | rpc_init_priority_wait_queue(&xprt->backlog, "xprt_backlog"); | 1134 | rpc_init_priority_wait_queue(&xprt->backlog, "xprt_backlog"); |
1123 | 1135 | ||
1124 | /* initialize free list */ | ||
1125 | for (req = &xprt->slot[xprt->max_reqs-1]; req >= &xprt->slot[0]; req--) | ||
1126 | list_add(&req->rq_list, &xprt->free); | ||
1127 | |||
1128 | xprt_init_xid(xprt); | 1136 | xprt_init_xid(xprt); |
1129 | 1137 | ||
1138 | xprt->xprt_net = get_net(net); | ||
1130 | } | 1139 | } |
1131 | 1140 | ||
1132 | /** | 1141 | /** |
@@ -1155,16 +1164,17 @@ found: | |||
1155 | if (IS_ERR(xprt)) { | 1164 | if (IS_ERR(xprt)) { |
1156 | dprintk("RPC: xprt_create_transport: failed, %ld\n", | 1165 | dprintk("RPC: xprt_create_transport: failed, %ld\n", |
1157 | -PTR_ERR(xprt)); | 1166 | -PTR_ERR(xprt)); |
1158 | return xprt; | 1167 | goto out; |
1159 | } | 1168 | } |
1160 | if (test_and_set_bit(XPRT_INITIALIZED, &xprt->state)) | 1169 | INIT_WORK(&xprt->task_cleanup, xprt_autoclose); |
1161 | /* ->setup returned a pre-initialized xprt: */ | 1170 | if (xprt_has_timer(xprt)) |
1162 | return xprt; | 1171 | setup_timer(&xprt->timer, xprt_init_autodisconnect, |
1163 | 1172 | (unsigned long)xprt); | |
1164 | xprt_init(xprt); | 1173 | else |
1165 | 1174 | init_timer(&xprt->timer); | |
1166 | dprintk("RPC: created transport %p with %u slots\n", xprt, | 1175 | dprintk("RPC: created transport %p with %u slots\n", xprt, |
1167 | xprt->max_reqs); | 1176 | xprt->max_reqs); |
1177 | out: | ||
1168 | return xprt; | 1178 | return xprt; |
1169 | } | 1179 | } |
1170 | 1180 | ||