1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33#include <linux/kernel.h>
34#include <linux/slab.h>
35#include <linux/in.h>
36
37#include "rds.h"
38#include "loop.h"
39
40static DEFINE_SPINLOCK(loop_conns_lock);
41static LIST_HEAD(loop_conns);
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60static int rds_loop_xmit(struct rds_connection *conn, struct rds_message *rm,
61 unsigned int hdr_off, unsigned int sg,
62 unsigned int off)
63{
64 struct scatterlist *sgp = &rm->data.op_sg[sg];
65 int ret = sizeof(struct rds_header) +
66 be32_to_cpu(rm->m_inc.i_hdr.h_len);
67
68
69 if (rm->m_inc.i_hdr.h_flags & RDS_FLAG_CONG_BITMAP) {
70 rds_cong_map_updated(conn->c_fcong, ~(u64) 0);
71 ret = min_t(int, ret, sgp->length - conn->c_xmit_data_off);
72 goto out;
73 }
74
75 BUG_ON(hdr_off || sg || off);
76
77 rds_inc_init(&rm->m_inc, conn, conn->c_laddr);
78
79 rds_message_addref(rm);
80
81 rds_recv_incoming(conn, conn->c_laddr, conn->c_faddr, &rm->m_inc,
82 GFP_KERNEL);
83
84 rds_send_drop_acked(conn, be64_to_cpu(rm->m_inc.i_hdr.h_sequence),
85 NULL);
86
87 rds_inc_put(&rm->m_inc);
88out:
89 return ret;
90}
91
92
93
94
95
96static void rds_loop_inc_free(struct rds_incoming *inc)
97{
98 struct rds_message *rm = container_of(inc, struct rds_message, m_inc);
99 rds_message_put(rm);
100}
101
102
103static int rds_loop_recv(struct rds_connection *conn)
104{
105 return 0;
106}
107
108struct rds_loop_connection {
109 struct list_head loop_node;
110 struct rds_connection *conn;
111};
112
113
114
115
116
117
118
119static int rds_loop_conn_alloc(struct rds_connection *conn, gfp_t gfp)
120{
121 struct rds_loop_connection *lc;
122 unsigned long flags;
123
124 lc = kzalloc(sizeof(struct rds_loop_connection), gfp);
125 if (!lc)
126 return -ENOMEM;
127
128 INIT_LIST_HEAD(&lc->loop_node);
129 lc->conn = conn;
130 conn->c_transport_data = lc;
131
132 spin_lock_irqsave(&loop_conns_lock, flags);
133 list_add_tail(&lc->loop_node, &loop_conns);
134 spin_unlock_irqrestore(&loop_conns_lock, flags);
135
136 return 0;
137}
138
139static void rds_loop_conn_free(void *arg)
140{
141 struct rds_loop_connection *lc = arg;
142 unsigned long flags;
143
144 rdsdebug("lc %p\n", lc);
145 spin_lock_irqsave(&loop_conns_lock, flags);
146 list_del(&lc->loop_node);
147 spin_unlock_irqrestore(&loop_conns_lock, flags);
148 kfree(lc);
149}
150
151static int rds_loop_conn_connect(struct rds_connection *conn)
152{
153 rds_connect_complete(conn);
154 return 0;
155}
156
157static void rds_loop_conn_shutdown(struct rds_connection *conn)
158{
159}
160
161void rds_loop_exit(void)
162{
163 struct rds_loop_connection *lc, *_lc;
164 LIST_HEAD(tmp_list);
165
166
167 spin_lock_irq(&loop_conns_lock);
168 list_splice(&loop_conns, &tmp_list);
169 INIT_LIST_HEAD(&loop_conns);
170 spin_unlock_irq(&loop_conns_lock);
171
172 list_for_each_entry_safe(lc, _lc, &tmp_list, loop_node) {
173 WARN_ON(lc->conn->c_passive);
174 rds_conn_destroy(lc->conn);
175 }
176}
177
178
179
180
181
182
183
184struct rds_transport rds_loop_transport = {
185 .xmit = rds_loop_xmit,
186 .recv = rds_loop_recv,
187 .conn_alloc = rds_loop_conn_alloc,
188 .conn_free = rds_loop_conn_free,
189 .conn_connect = rds_loop_conn_connect,
190 .conn_shutdown = rds_loop_conn_shutdown,
191 .inc_copy_to_user = rds_message_inc_copy_to_user,
192 .inc_free = rds_loop_inc_free,
193 .t_name = "loopback",
194};
195