Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-2.0-only
2 : : /*
3 : : * linux/fs/9p/trans_fd.c
4 : : *
5 : : * Fd transport layer. Includes deprecated socket layer.
6 : : *
7 : : * Copyright (C) 2006 by Russ Cox <rsc@swtch.com>
8 : : * Copyright (C) 2004-2005 by Latchesar Ionkov <lucho@ionkov.net>
9 : : * Copyright (C) 2004-2008 by Eric Van Hensbergen <ericvh@gmail.com>
10 : : * Copyright (C) 1997-2002 by Ron Minnich <rminnich@sarnoff.com>
11 : : */
12 : :
13 : : #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
14 : :
15 : : #include <linux/in.h>
16 : : #include <linux/module.h>
17 : : #include <linux/net.h>
18 : : #include <linux/ipv6.h>
19 : : #include <linux/kthread.h>
20 : : #include <linux/errno.h>
21 : : #include <linux/kernel.h>
22 : : #include <linux/un.h>
23 : : #include <linux/uaccess.h>
24 : : #include <linux/inet.h>
25 : : #include <linux/idr.h>
26 : : #include <linux/file.h>
27 : : #include <linux/parser.h>
28 : : #include <linux/slab.h>
29 : : #include <linux/seq_file.h>
30 : : #include <net/9p/9p.h>
31 : : #include <net/9p/client.h>
32 : : #include <net/9p/transport.h>
33 : :
34 : : #include <linux/syscalls.h> /* killme */
35 : :
36 : : #define P9_PORT 564
37 : : #define MAX_SOCK_BUF (64*1024)
38 : : #define MAXPOLLWADDR 2
39 : :
40 : : static struct p9_trans_module p9_tcp_trans;
41 : : static struct p9_trans_module p9_fd_trans;
42 : :
43 : : /**
44 : : * struct p9_fd_opts - per-transport options
45 : : * @rfd: file descriptor for reading (trans=fd)
46 : : * @wfd: file descriptor for writing (trans=fd)
47 : : * @port: port to connect to (trans=tcp)
48 : : *
49 : : */
50 : :
51 : : struct p9_fd_opts {
52 : : int rfd;
53 : : int wfd;
54 : : u16 port;
55 : : bool privport;
56 : : };
57 : :
58 : : /*
59 : : * Option Parsing (code inspired by NFS code)
60 : : * - a little lazy - parse all fd-transport options
61 : : */
62 : :
63 : : enum {
64 : : /* Options that take integer arguments */
65 : : Opt_port, Opt_rfdno, Opt_wfdno, Opt_err,
66 : : /* Options that take no arguments */
67 : : Opt_privport,
68 : : };
69 : :
70 : : static const match_table_t tokens = {
71 : : {Opt_port, "port=%u"},
72 : : {Opt_rfdno, "rfdno=%u"},
73 : : {Opt_wfdno, "wfdno=%u"},
74 : : {Opt_privport, "privport"},
75 : : {Opt_err, NULL},
76 : : };
77 : :
78 : : enum {
79 : : Rworksched = 1, /* read work scheduled or running */
80 : : Rpending = 2, /* can read */
81 : : Wworksched = 4, /* write work scheduled or running */
82 : : Wpending = 8, /* can write */
83 : : };
84 : :
85 : : struct p9_poll_wait {
86 : : struct p9_conn *conn;
87 : : wait_queue_entry_t wait;
88 : : wait_queue_head_t *wait_addr;
89 : : };
90 : :
91 : : /**
92 : : * struct p9_conn - fd mux connection state information
93 : : * @mux_list: list link for mux to manage multiple connections (?)
94 : : * @client: reference to client instance for this connection
95 : : * @err: error state
96 : : * @req_list: accounting for requests which have been sent
97 : : * @unsent_req_list: accounting for requests that haven't been sent
98 : : * @req: current request being processed (if any)
99 : : * @tmp_buf: temporary buffer to read in header
100 : : * @rc: temporary fcall for reading current frame
101 : : * @wpos: write position for current frame
102 : : * @wsize: amount of data to write for current frame
103 : : * @wbuf: current write buffer
104 : : * @poll_pending_link: pending links to be polled per conn
105 : : * @poll_wait: array of wait_q's for various worker threads
106 : : * @pt: poll state
107 : : * @rq: current read work
108 : : * @wq: current write work
109 : : * @wsched: ????
110 : : *
111 : : */
112 : :
113 : : struct p9_conn {
114 : : struct list_head mux_list;
115 : : struct p9_client *client;
116 : : int err;
117 : : struct list_head req_list;
118 : : struct list_head unsent_req_list;
119 : : struct p9_req_t *rreq;
120 : : struct p9_req_t *wreq;
121 : : char tmp_buf[7];
122 : : struct p9_fcall rc;
123 : : int wpos;
124 : : int wsize;
125 : : char *wbuf;
126 : : struct list_head poll_pending_link;
127 : : struct p9_poll_wait poll_wait[MAXPOLLWADDR];
128 : : poll_table pt;
129 : : struct work_struct rq;
130 : : struct work_struct wq;
131 : : unsigned long wsched;
132 : : };
133 : :
134 : : /**
135 : : * struct p9_trans_fd - transport state
136 : : * @rd: reference to file to read from
137 : : * @wr: reference of file to write to
138 : : * @conn: connection state reference
139 : : *
140 : : */
141 : :
142 : : struct p9_trans_fd {
143 : : struct file *rd;
144 : : struct file *wr;
145 : : struct p9_conn conn;
146 : : };
147 : :
148 : : static void p9_poll_workfn(struct work_struct *work);
149 : :
150 : : static DEFINE_SPINLOCK(p9_poll_lock);
151 : : static LIST_HEAD(p9_poll_pending_list);
152 : : static DECLARE_WORK(p9_poll_work, p9_poll_workfn);
153 : :
154 : : static unsigned int p9_ipport_resv_min = P9_DEF_MIN_RESVPORT;
155 : : static unsigned int p9_ipport_resv_max = P9_DEF_MAX_RESVPORT;
156 : :
157 : 0 : static void p9_mux_poll_stop(struct p9_conn *m)
158 : : {
159 : 0 : unsigned long flags;
160 : 0 : int i;
161 : :
162 [ # # ]: 0 : for (i = 0; i < ARRAY_SIZE(m->poll_wait); i++) {
163 : 0 : struct p9_poll_wait *pwait = &m->poll_wait[i];
164 : :
165 [ # # ]: 0 : if (pwait->wait_addr) {
166 : 0 : remove_wait_queue(pwait->wait_addr, &pwait->wait);
167 : 0 : pwait->wait_addr = NULL;
168 : : }
169 : : }
170 : :
171 : 0 : spin_lock_irqsave(&p9_poll_lock, flags);
172 : 0 : list_del_init(&m->poll_pending_link);
173 : 0 : spin_unlock_irqrestore(&p9_poll_lock, flags);
174 : :
175 : 0 : flush_work(&p9_poll_work);
176 : 0 : }
177 : :
178 : : /**
179 : : * p9_conn_cancel - cancel all pending requests with error
180 : : * @m: mux data
181 : : * @err: error code
182 : : *
183 : : */
184 : :
185 : 0 : static void p9_conn_cancel(struct p9_conn *m, int err)
186 : : {
187 : 0 : struct p9_req_t *req, *rtmp;
188 : 0 : LIST_HEAD(cancel_list);
189 : :
190 : 0 : p9_debug(P9_DEBUG_ERROR, "mux %p err %d\n", m, err);
191 : :
192 : 0 : spin_lock(&m->client->lock);
193 : :
194 [ # # ]: 0 : if (m->err) {
195 : 0 : spin_unlock(&m->client->lock);
196 : 0 : return;
197 : : }
198 : :
199 : 0 : m->err = err;
200 : :
201 [ # # ]: 0 : list_for_each_entry_safe(req, rtmp, &m->req_list, req_list) {
202 : 0 : list_move(&req->req_list, &cancel_list);
203 : : }
204 [ # # ]: 0 : list_for_each_entry_safe(req, rtmp, &m->unsent_req_list, req_list) {
205 : 0 : list_move(&req->req_list, &cancel_list);
206 : : }
207 : :
208 [ # # ]: 0 : list_for_each_entry_safe(req, rtmp, &cancel_list, req_list) {
209 : 0 : p9_debug(P9_DEBUG_ERROR, "call back req %p\n", req);
210 [ # # ]: 0 : list_del(&req->req_list);
211 [ # # ]: 0 : if (!req->t_err)
212 : 0 : req->t_err = err;
213 : 0 : p9_client_cb(m->client, req, REQ_STATUS_ERROR);
214 : : }
215 : 0 : spin_unlock(&m->client->lock);
216 : : }
217 : :
218 : : static __poll_t
219 : 0 : p9_fd_poll(struct p9_client *client, struct poll_table_struct *pt, int *err)
220 : : {
221 : 0 : __poll_t ret;
222 : 0 : struct p9_trans_fd *ts = NULL;
223 : :
224 [ # # # # ]: 0 : if (client && client->status == Connected)
225 : 0 : ts = client->trans;
226 : :
227 [ # # ]: 0 : if (!ts) {
228 [ # # ]: 0 : if (err)
229 : 0 : *err = -EREMOTEIO;
230 : 0 : return EPOLLERR;
231 : : }
232 : :
233 [ # # ]: 0 : ret = vfs_poll(ts->rd, pt);
234 [ # # ]: 0 : if (ts->rd != ts->wr)
235 [ # # ]: 0 : ret = (ret & ~EPOLLOUT) | (vfs_poll(ts->wr, pt) & ~EPOLLIN);
236 : : return ret;
237 : : }
238 : :
239 : : /**
240 : : * p9_fd_read- read from a fd
241 : : * @client: client instance
242 : : * @v: buffer to receive data into
243 : : * @len: size of receive buffer
244 : : *
245 : : */
246 : :
247 : 0 : static int p9_fd_read(struct p9_client *client, void *v, int len)
248 : : {
249 : 0 : int ret;
250 : 0 : struct p9_trans_fd *ts = NULL;
251 : 0 : loff_t pos;
252 : :
253 [ # # # # ]: 0 : if (client && client->status != Disconnected)
254 : 0 : ts = client->trans;
255 : :
256 [ # # ]: 0 : if (!ts)
257 : : return -EREMOTEIO;
258 : :
259 : 0 : if (!(ts->rd->f_flags & O_NONBLOCK))
260 : : p9_debug(P9_DEBUG_ERROR, "blocking read ...\n");
261 : :
262 : 0 : pos = ts->rd->f_pos;
263 : 0 : ret = kernel_read(ts->rd, v, len, &pos);
264 [ # # # # ]: 0 : if (ret <= 0 && ret != -ERESTARTSYS && ret != -EAGAIN)
265 : 0 : client->status = Disconnected;
266 : : return ret;
267 : : }
268 : :
269 : : /**
270 : : * p9_read_work - called when there is some data to be read from a transport
271 : : * @work: container of work to be done
272 : : *
273 : : */
274 : :
275 : 0 : static void p9_read_work(struct work_struct *work)
276 : : {
277 : 0 : __poll_t n;
278 : 0 : int err;
279 : 0 : struct p9_conn *m;
280 : :
281 : 0 : m = container_of(work, struct p9_conn, rq);
282 : :
283 [ # # ]: 0 : if (m->err < 0)
284 : : return;
285 : :
286 : 0 : p9_debug(P9_DEBUG_TRANS, "start mux %p pos %zd\n", m, m->rc.offset);
287 : :
288 [ # # ]: 0 : if (!m->rc.sdata) {
289 : 0 : m->rc.sdata = m->tmp_buf;
290 : 0 : m->rc.offset = 0;
291 : 0 : m->rc.capacity = 7; /* start by reading header */
292 : : }
293 : :
294 : 0 : clear_bit(Rpending, &m->wsched);
295 : 0 : p9_debug(P9_DEBUG_TRANS, "read mux %p pos %zd size: %zd = %zd\n",
296 : : m, m->rc.offset, m->rc.capacity,
297 : : m->rc.capacity - m->rc.offset);
298 : 0 : err = p9_fd_read(m->client, m->rc.sdata + m->rc.offset,
299 : 0 : m->rc.capacity - m->rc.offset);
300 : 0 : p9_debug(P9_DEBUG_TRANS, "mux %p got %d bytes\n", m, err);
301 [ # # ]: 0 : if (err == -EAGAIN)
302 : 0 : goto end_clear;
303 : :
304 [ # # ]: 0 : if (err <= 0)
305 : 0 : goto error;
306 : :
307 : 0 : m->rc.offset += err;
308 : :
309 : : /* header read in */
310 [ # # # # ]: 0 : if ((!m->rreq) && (m->rc.offset == m->rc.capacity)) {
311 : 0 : p9_debug(P9_DEBUG_TRANS, "got new header\n");
312 : :
313 : : /* Header size */
314 : 0 : m->rc.size = 7;
315 : 0 : err = p9_parse_header(&m->rc, &m->rc.size, NULL, NULL, 0);
316 [ # # ]: 0 : if (err) {
317 : 0 : p9_debug(P9_DEBUG_ERROR,
318 : : "error parsing header: %d\n", err);
319 : 0 : goto error;
320 : : }
321 : :
322 [ # # ]: 0 : if (m->rc.size >= m->client->msize) {
323 : 0 : p9_debug(P9_DEBUG_ERROR,
324 : : "requested packet size too big: %d\n",
325 : : m->rc.size);
326 : 0 : err = -EIO;
327 : 0 : goto error;
328 : : }
329 : :
330 : 0 : p9_debug(P9_DEBUG_TRANS,
331 : : "mux %p pkt: size: %d bytes tag: %d\n",
332 : : m, m->rc.size, m->rc.tag);
333 : :
334 : 0 : m->rreq = p9_tag_lookup(m->client, m->rc.tag);
335 [ # # # # ]: 0 : if (!m->rreq || (m->rreq->status != REQ_STATUS_SENT)) {
336 : 0 : p9_debug(P9_DEBUG_ERROR, "Unexpected packet tag %d\n",
337 : : m->rc.tag);
338 : 0 : err = -EIO;
339 : 0 : goto error;
340 : : }
341 : :
342 [ # # ]: 0 : if (!m->rreq->rc.sdata) {
343 : 0 : p9_debug(P9_DEBUG_ERROR,
344 : : "No recv fcall for tag %d (req %p), disconnecting!\n",
345 : : m->rc.tag, m->rreq);
346 : 0 : m->rreq = NULL;
347 : 0 : err = -EIO;
348 : 0 : goto error;
349 : : }
350 : 0 : m->rc.sdata = m->rreq->rc.sdata;
351 : 0 : memcpy(m->rc.sdata, m->tmp_buf, m->rc.capacity);
352 : 0 : m->rc.capacity = m->rc.size;
353 : : }
354 : :
355 : : /* packet is read in
356 : : * not an else because some packets (like clunk) have no payload
357 : : */
358 [ # # # # ]: 0 : if ((m->rreq) && (m->rc.offset == m->rc.capacity)) {
359 : 0 : p9_debug(P9_DEBUG_TRANS, "got new packet\n");
360 : 0 : m->rreq->rc.size = m->rc.offset;
361 : 0 : spin_lock(&m->client->lock);
362 [ # # ]: 0 : if (m->rreq->status == REQ_STATUS_SENT) {
363 : 0 : list_del(&m->rreq->req_list);
364 : 0 : p9_client_cb(m->client, m->rreq, REQ_STATUS_RCVD);
365 : : } else {
366 : 0 : spin_unlock(&m->client->lock);
367 : 0 : p9_debug(P9_DEBUG_ERROR,
368 : : "Request tag %d errored out while we were reading the reply\n",
369 : : m->rc.tag);
370 : 0 : err = -EIO;
371 : 0 : goto error;
372 : : }
373 : 0 : spin_unlock(&m->client->lock);
374 : 0 : m->rc.sdata = NULL;
375 : 0 : m->rc.offset = 0;
376 : 0 : m->rc.capacity = 0;
377 : 0 : p9_req_put(m->rreq);
378 : 0 : m->rreq = NULL;
379 : : }
380 : :
381 : 0 : end_clear:
382 : 0 : clear_bit(Rworksched, &m->wsched);
383 : :
384 [ # # ]: 0 : if (!list_empty(&m->req_list)) {
385 [ # # ]: 0 : if (test_and_clear_bit(Rpending, &m->wsched))
386 : : n = EPOLLIN;
387 : : else
388 : 0 : n = p9_fd_poll(m->client, NULL, NULL);
389 : :
390 [ # # # # ]: 0 : if ((n & EPOLLIN) && !test_and_set_bit(Rworksched, &m->wsched)) {
391 : 0 : p9_debug(P9_DEBUG_TRANS, "sched read work %p\n", m);
392 : 0 : schedule_work(&m->rq);
393 : : }
394 : : }
395 : :
396 : : return;
397 : 0 : error:
398 : 0 : p9_conn_cancel(m, err);
399 : 0 : clear_bit(Rworksched, &m->wsched);
400 : : }
401 : :
402 : : /**
403 : : * p9_fd_write - write to a socket
404 : : * @client: client instance
405 : : * @v: buffer to send data from
406 : : * @len: size of send buffer
407 : : *
408 : : */
409 : :
410 : 0 : static int p9_fd_write(struct p9_client *client, void *v, int len)
411 : : {
412 : 0 : ssize_t ret;
413 : 0 : struct p9_trans_fd *ts = NULL;
414 : :
415 [ # # # # ]: 0 : if (client && client->status != Disconnected)
416 : 0 : ts = client->trans;
417 : :
418 [ # # ]: 0 : if (!ts)
419 : : return -EREMOTEIO;
420 : :
421 : 0 : if (!(ts->wr->f_flags & O_NONBLOCK))
422 : : p9_debug(P9_DEBUG_ERROR, "blocking write ...\n");
423 : :
424 : 0 : ret = kernel_write(ts->wr, v, len, &ts->wr->f_pos);
425 [ # # # # ]: 0 : if (ret <= 0 && ret != -ERESTARTSYS && ret != -EAGAIN)
426 : 0 : client->status = Disconnected;
427 : 0 : return ret;
428 : : }
429 : :
430 : : /**
431 : : * p9_write_work - called when a transport can send some data
432 : : * @work: container for work to be done
433 : : *
434 : : */
435 : :
436 : 0 : static void p9_write_work(struct work_struct *work)
437 : : {
438 : 0 : __poll_t n;
439 : 0 : int err;
440 : 0 : struct p9_conn *m;
441 : 0 : struct p9_req_t *req;
442 : :
443 : 0 : m = container_of(work, struct p9_conn, wq);
444 : :
445 [ # # ]: 0 : if (m->err < 0) {
446 : 0 : clear_bit(Wworksched, &m->wsched);
447 : 0 : return;
448 : : }
449 : :
450 [ # # ]: 0 : if (!m->wsize) {
451 : 0 : spin_lock(&m->client->lock);
452 [ # # ]: 0 : if (list_empty(&m->unsent_req_list)) {
453 : 0 : clear_bit(Wworksched, &m->wsched);
454 : 0 : spin_unlock(&m->client->lock);
455 : 0 : return;
456 : : }
457 : :
458 : 0 : req = list_entry(m->unsent_req_list.next, struct p9_req_t,
459 : : req_list);
460 : 0 : req->status = REQ_STATUS_SENT;
461 : 0 : p9_debug(P9_DEBUG_TRANS, "move req %p\n", req);
462 : 0 : list_move_tail(&req->req_list, &m->req_list);
463 : :
464 : 0 : m->wbuf = req->tc.sdata;
465 : 0 : m->wsize = req->tc.size;
466 : 0 : m->wpos = 0;
467 : 0 : p9_req_get(req);
468 : 0 : m->wreq = req;
469 : 0 : spin_unlock(&m->client->lock);
470 : : }
471 : :
472 : 0 : p9_debug(P9_DEBUG_TRANS, "mux %p pos %d size %d\n",
473 : : m, m->wpos, m->wsize);
474 : 0 : clear_bit(Wpending, &m->wsched);
475 : 0 : err = p9_fd_write(m->client, m->wbuf + m->wpos, m->wsize - m->wpos);
476 : 0 : p9_debug(P9_DEBUG_TRANS, "mux %p sent %d bytes\n", m, err);
477 [ # # ]: 0 : if (err == -EAGAIN)
478 : 0 : goto end_clear;
479 : :
480 : :
481 [ # # ]: 0 : if (err < 0)
482 : 0 : goto error;
483 [ # # ]: 0 : else if (err == 0) {
484 : 0 : err = -EREMOTEIO;
485 : 0 : goto error;
486 : : }
487 : :
488 : 0 : m->wpos += err;
489 [ # # ]: 0 : if (m->wpos == m->wsize) {
490 : 0 : m->wpos = m->wsize = 0;
491 : 0 : p9_req_put(m->wreq);
492 : 0 : m->wreq = NULL;
493 : : }
494 : :
495 : 0 : end_clear:
496 : 0 : clear_bit(Wworksched, &m->wsched);
497 : :
498 [ # # # # ]: 0 : if (m->wsize || !list_empty(&m->unsent_req_list)) {
499 [ # # ]: 0 : if (test_and_clear_bit(Wpending, &m->wsched))
500 : : n = EPOLLOUT;
501 : : else
502 : 0 : n = p9_fd_poll(m->client, NULL, NULL);
503 : :
504 [ # # # # ]: 0 : if ((n & EPOLLOUT) &&
505 : 0 : !test_and_set_bit(Wworksched, &m->wsched)) {
506 : 0 : p9_debug(P9_DEBUG_TRANS, "sched write work %p\n", m);
507 : 0 : schedule_work(&m->wq);
508 : : }
509 : : }
510 : :
511 : : return;
512 : :
513 : 0 : error:
514 : 0 : p9_conn_cancel(m, err);
515 : 0 : clear_bit(Wworksched, &m->wsched);
516 : : }
517 : :
518 : 0 : static int p9_pollwake(wait_queue_entry_t *wait, unsigned int mode, int sync, void *key)
519 : : {
520 : 0 : struct p9_poll_wait *pwait =
521 : 0 : container_of(wait, struct p9_poll_wait, wait);
522 : 0 : struct p9_conn *m = pwait->conn;
523 : 0 : unsigned long flags;
524 : :
525 : 0 : spin_lock_irqsave(&p9_poll_lock, flags);
526 [ # # ]: 0 : if (list_empty(&m->poll_pending_link))
527 : 0 : list_add_tail(&m->poll_pending_link, &p9_poll_pending_list);
528 : 0 : spin_unlock_irqrestore(&p9_poll_lock, flags);
529 : :
530 : 0 : schedule_work(&p9_poll_work);
531 : 0 : return 1;
532 : : }
533 : :
534 : : /**
535 : : * p9_pollwait - add poll task to the wait queue
536 : : * @filp: file pointer being polled
537 : : * @wait_address: wait_q to block on
538 : : * @p: poll state
539 : : *
540 : : * called by files poll operation to add v9fs-poll task to files wait queue
541 : : */
542 : :
543 : : static void
544 : 0 : p9_pollwait(struct file *filp, wait_queue_head_t *wait_address, poll_table *p)
545 : : {
546 : 0 : struct p9_conn *m = container_of(p, struct p9_conn, pt);
547 : 0 : struct p9_poll_wait *pwait = NULL;
548 : 0 : int i;
549 : :
550 [ # # ]: 0 : for (i = 0; i < ARRAY_SIZE(m->poll_wait); i++) {
551 [ # # ]: 0 : if (m->poll_wait[i].wait_addr == NULL) {
552 : 0 : pwait = &m->poll_wait[i];
553 : 0 : break;
554 : : }
555 : : }
556 : :
557 [ # # ]: 0 : if (!pwait) {
558 : : p9_debug(P9_DEBUG_ERROR, "not enough wait_address slots\n");
559 : : return;
560 : : }
561 : :
562 : 0 : pwait->conn = m;
563 : 0 : pwait->wait_addr = wait_address;
564 : 0 : init_waitqueue_func_entry(&pwait->wait, p9_pollwake);
565 : 0 : add_wait_queue(wait_address, &pwait->wait);
566 : : }
567 : :
568 : : /**
569 : : * p9_conn_create - initialize the per-session mux data
570 : : * @client: client instance
571 : : *
572 : : * Note: Creates the polling task if this is the first session.
573 : : */
574 : :
575 : 0 : static void p9_conn_create(struct p9_client *client)
576 : : {
577 : 0 : __poll_t n;
578 : 0 : struct p9_trans_fd *ts = client->trans;
579 : 0 : struct p9_conn *m = &ts->conn;
580 : :
581 : 0 : p9_debug(P9_DEBUG_TRANS, "client %p msize %d\n", client, client->msize);
582 : :
583 : 0 : INIT_LIST_HEAD(&m->mux_list);
584 : 0 : m->client = client;
585 : :
586 : 0 : INIT_LIST_HEAD(&m->req_list);
587 : 0 : INIT_LIST_HEAD(&m->unsent_req_list);
588 : 0 : INIT_WORK(&m->rq, p9_read_work);
589 : 0 : INIT_WORK(&m->wq, p9_write_work);
590 : 0 : INIT_LIST_HEAD(&m->poll_pending_link);
591 : 0 : init_poll_funcptr(&m->pt, p9_pollwait);
592 : :
593 : 0 : n = p9_fd_poll(client, &m->pt, NULL);
594 [ # # ]: 0 : if (n & EPOLLIN) {
595 : 0 : p9_debug(P9_DEBUG_TRANS, "mux %p can read\n", m);
596 : 0 : set_bit(Rpending, &m->wsched);
597 : : }
598 : :
599 [ # # ]: 0 : if (n & EPOLLOUT) {
600 : 0 : p9_debug(P9_DEBUG_TRANS, "mux %p can write\n", m);
601 : 0 : set_bit(Wpending, &m->wsched);
602 : : }
603 : 0 : }
604 : :
605 : : /**
606 : : * p9_poll_mux - polls a mux and schedules read or write works if necessary
607 : : * @m: connection to poll
608 : : *
609 : : */
610 : :
611 : 0 : static void p9_poll_mux(struct p9_conn *m)
612 : : {
613 : 0 : __poll_t n;
614 : 0 : int err = -ECONNRESET;
615 : :
616 [ # # ]: 0 : if (m->err < 0)
617 : 0 : return;
618 : :
619 : 0 : n = p9_fd_poll(m->client, NULL, &err);
620 [ # # ]: 0 : if (n & (EPOLLERR | EPOLLHUP | EPOLLNVAL)) {
621 : 0 : p9_debug(P9_DEBUG_TRANS, "error mux %p err %d\n", m, n);
622 : 0 : p9_conn_cancel(m, err);
623 : : }
624 : :
625 [ # # ]: 0 : if (n & EPOLLIN) {
626 : 0 : set_bit(Rpending, &m->wsched);
627 : 0 : p9_debug(P9_DEBUG_TRANS, "mux %p can read\n", m);
628 [ # # ]: 0 : if (!test_and_set_bit(Rworksched, &m->wsched)) {
629 : 0 : p9_debug(P9_DEBUG_TRANS, "sched read work %p\n", m);
630 : 0 : schedule_work(&m->rq);
631 : : }
632 : : }
633 : :
634 [ # # ]: 0 : if (n & EPOLLOUT) {
635 : 0 : set_bit(Wpending, &m->wsched);
636 : 0 : p9_debug(P9_DEBUG_TRANS, "mux %p can write\n", m);
637 [ # # # # : 0 : if ((m->wsize || !list_empty(&m->unsent_req_list)) &&
# # ]
638 : 0 : !test_and_set_bit(Wworksched, &m->wsched)) {
639 : 0 : p9_debug(P9_DEBUG_TRANS, "sched write work %p\n", m);
640 : 0 : schedule_work(&m->wq);
641 : : }
642 : : }
643 : : }
644 : :
645 : : /**
646 : : * p9_fd_request - send 9P request
647 : : * The function can sleep until the request is scheduled for sending.
648 : : * The function can be interrupted. Return from the function is not
649 : : * a guarantee that the request is sent successfully.
650 : : *
651 : : * @client: client instance
652 : : * @req: request to be sent
653 : : *
654 : : */
655 : :
656 : 0 : static int p9_fd_request(struct p9_client *client, struct p9_req_t *req)
657 : : {
658 : 0 : __poll_t n;
659 : 0 : struct p9_trans_fd *ts = client->trans;
660 : 0 : struct p9_conn *m = &ts->conn;
661 : :
662 : 0 : p9_debug(P9_DEBUG_TRANS, "mux %p task %p tcall %p id %d\n",
663 : : m, current, &req->tc, req->tc.id);
664 [ # # ]: 0 : if (m->err < 0)
665 : : return m->err;
666 : :
667 : 0 : spin_lock(&client->lock);
668 : 0 : req->status = REQ_STATUS_UNSENT;
669 : 0 : list_add_tail(&req->req_list, &m->unsent_req_list);
670 : 0 : spin_unlock(&client->lock);
671 : :
672 [ # # ]: 0 : if (test_and_clear_bit(Wpending, &m->wsched))
673 : : n = EPOLLOUT;
674 : : else
675 : 0 : n = p9_fd_poll(m->client, NULL, NULL);
676 : :
677 [ # # # # ]: 0 : if (n & EPOLLOUT && !test_and_set_bit(Wworksched, &m->wsched))
678 : 0 : schedule_work(&m->wq);
679 : :
680 : : return 0;
681 : : }
682 : :
683 : 0 : static int p9_fd_cancel(struct p9_client *client, struct p9_req_t *req)
684 : : {
685 : 0 : int ret = 1;
686 : :
687 : 0 : p9_debug(P9_DEBUG_TRANS, "client %p req %p\n", client, req);
688 : :
689 : 0 : spin_lock(&client->lock);
690 : :
691 [ # # ]: 0 : if (req->status == REQ_STATUS_UNSENT) {
692 : 0 : list_del(&req->req_list);
693 : 0 : req->status = REQ_STATUS_FLSHD;
694 : 0 : p9_req_put(req);
695 : 0 : ret = 0;
696 : : }
697 : 0 : spin_unlock(&client->lock);
698 : :
699 : 0 : return ret;
700 : : }
701 : :
702 : 0 : static int p9_fd_cancelled(struct p9_client *client, struct p9_req_t *req)
703 : : {
704 : 0 : p9_debug(P9_DEBUG_TRANS, "client %p req %p\n", client, req);
705 : :
706 : : /* we haven't received a response for oldreq,
707 : : * remove it from the list.
708 : : */
709 : 0 : spin_lock(&client->lock);
710 : 0 : list_del(&req->req_list);
711 : 0 : spin_unlock(&client->lock);
712 : 0 : p9_req_put(req);
713 : :
714 : 0 : return 0;
715 : : }
716 : :
717 : 0 : static int p9_fd_show_options(struct seq_file *m, struct p9_client *clnt)
718 : : {
719 [ # # ]: 0 : if (clnt->trans_mod == &p9_tcp_trans) {
720 [ # # ]: 0 : if (clnt->trans_opts.tcp.port != P9_PORT)
721 : 0 : seq_printf(m, ",port=%u", clnt->trans_opts.tcp.port);
722 [ # # ]: 0 : } else if (clnt->trans_mod == &p9_fd_trans) {
723 [ # # ]: 0 : if (clnt->trans_opts.fd.rfd != ~0)
724 : 0 : seq_printf(m, ",rfd=%u", clnt->trans_opts.fd.rfd);
725 [ # # ]: 0 : if (clnt->trans_opts.fd.wfd != ~0)
726 : 0 : seq_printf(m, ",wfd=%u", clnt->trans_opts.fd.wfd);
727 : : }
728 : 0 : return 0;
729 : : }
730 : :
731 : : /**
732 : : * parse_opts - parse mount options into p9_fd_opts structure
733 : : * @params: options string passed from mount
734 : : * @opts: fd transport-specific structure to parse options into
735 : : *
736 : : * Returns 0 upon success, -ERRNO upon failure
737 : : */
738 : :
739 : 0 : static int parse_opts(char *params, struct p9_fd_opts *opts)
740 : : {
741 : 0 : char *p;
742 : 0 : substring_t args[MAX_OPT_ARGS];
743 : 0 : int option;
744 : 0 : char *options, *tmp_options;
745 : :
746 : 0 : opts->port = P9_PORT;
747 : 0 : opts->rfd = ~0;
748 : 0 : opts->wfd = ~0;
749 : 0 : opts->privport = false;
750 : :
751 [ # # ]: 0 : if (!params)
752 : : return 0;
753 : :
754 : 0 : tmp_options = kstrdup(params, GFP_KERNEL);
755 [ # # ]: 0 : if (!tmp_options) {
756 : : p9_debug(P9_DEBUG_ERROR,
757 : : "failed to allocate copy of option string\n");
758 : : return -ENOMEM;
759 : : }
760 : 0 : options = tmp_options;
761 : :
762 [ # # ]: 0 : while ((p = strsep(&options, ",")) != NULL) {
763 : 0 : int token;
764 : 0 : int r;
765 [ # # ]: 0 : if (!*p)
766 : 0 : continue;
767 : 0 : token = match_token(p, tokens, args);
768 [ # # ]: 0 : if ((token != Opt_err) && (token != Opt_privport)) {
769 : 0 : r = match_int(&args[0], &option);
770 [ # # ]: 0 : if (r < 0) {
771 : 0 : p9_debug(P9_DEBUG_ERROR,
772 : : "integer field, but no integer?\n");
773 : 0 : continue;
774 : : }
775 : : }
776 [ # # # # : 0 : switch (token) {
# ]
777 : 0 : case Opt_port:
778 : 0 : opts->port = option;
779 : 0 : break;
780 : 0 : case Opt_rfdno:
781 : 0 : opts->rfd = option;
782 : 0 : break;
783 : 0 : case Opt_wfdno:
784 : 0 : opts->wfd = option;
785 : 0 : break;
786 : 0 : case Opt_privport:
787 : 0 : opts->privport = true;
788 : 0 : break;
789 : 0 : default:
790 : 0 : continue;
791 : : }
792 : : }
793 : :
794 : 0 : kfree(tmp_options);
795 : 0 : return 0;
796 : : }
797 : :
798 : : static int p9_fd_open(struct p9_client *client, int rfd, int wfd)
799 : : {
800 : : struct p9_trans_fd *ts = kzalloc(sizeof(struct p9_trans_fd),
801 : : GFP_KERNEL);
802 : : if (!ts)
803 : : return -ENOMEM;
804 : :
805 : : ts->rd = fget(rfd);
806 : : ts->wr = fget(wfd);
807 : : if (!ts->rd || !ts->wr) {
808 : : if (ts->rd)
809 : : fput(ts->rd);
810 : : if (ts->wr)
811 : : fput(ts->wr);
812 : : kfree(ts);
813 : : return -EIO;
814 : : }
815 : :
816 : : client->trans = ts;
817 : : client->status = Connected;
818 : :
819 : : return 0;
820 : : }
821 : :
822 : 0 : static int p9_socket_open(struct p9_client *client, struct socket *csocket)
823 : : {
824 : 0 : struct p9_trans_fd *p;
825 : 0 : struct file *file;
826 : :
827 : 0 : p = kzalloc(sizeof(struct p9_trans_fd), GFP_KERNEL);
828 [ # # ]: 0 : if (!p)
829 : : return -ENOMEM;
830 : :
831 : 0 : csocket->sk->sk_allocation = GFP_NOIO;
832 : 0 : file = sock_alloc_file(csocket, 0, NULL);
833 [ # # ]: 0 : if (IS_ERR(file)) {
834 : 0 : pr_err("%s (%d): failed to map fd\n",
835 : : __func__, task_pid_nr(current));
836 : 0 : kfree(p);
837 : 0 : return PTR_ERR(file);
838 : : }
839 : :
840 : 0 : get_file(file);
841 : 0 : p->wr = p->rd = file;
842 : 0 : client->trans = p;
843 : 0 : client->status = Connected;
844 : :
845 : 0 : p->rd->f_flags |= O_NONBLOCK;
846 : :
847 : 0 : p9_conn_create(client);
848 : 0 : return 0;
849 : : }
850 : :
851 : : /**
852 : : * p9_mux_destroy - cancels all pending requests of mux
853 : : * @m: mux to destroy
854 : : *
855 : : */
856 : :
857 : 0 : static void p9_conn_destroy(struct p9_conn *m)
858 : : {
859 : 0 : p9_debug(P9_DEBUG_TRANS, "mux %p prev %p next %p\n",
860 : : m, m->mux_list.prev, m->mux_list.next);
861 : :
862 : 0 : p9_mux_poll_stop(m);
863 : 0 : cancel_work_sync(&m->rq);
864 [ # # ]: 0 : if (m->rreq) {
865 : 0 : p9_req_put(m->rreq);
866 : 0 : m->rreq = NULL;
867 : : }
868 : 0 : cancel_work_sync(&m->wq);
869 [ # # ]: 0 : if (m->wreq) {
870 : 0 : p9_req_put(m->wreq);
871 : 0 : m->wreq = NULL;
872 : : }
873 : :
874 : 0 : p9_conn_cancel(m, -ECONNRESET);
875 : :
876 : 0 : m->client = NULL;
877 : 0 : }
878 : :
879 : : /**
880 : : * p9_fd_close - shutdown file descriptor transport
881 : : * @client: client instance
882 : : *
883 : : */
884 : :
885 : 0 : static void p9_fd_close(struct p9_client *client)
886 : : {
887 : 0 : struct p9_trans_fd *ts;
888 : :
889 [ # # ]: 0 : if (!client)
890 : : return;
891 : :
892 : 0 : ts = client->trans;
893 [ # # ]: 0 : if (!ts)
894 : : return;
895 : :
896 : 0 : client->status = Disconnected;
897 : :
898 : 0 : p9_conn_destroy(&ts->conn);
899 : :
900 [ # # ]: 0 : if (ts->rd)
901 : 0 : fput(ts->rd);
902 [ # # ]: 0 : if (ts->wr)
903 : 0 : fput(ts->wr);
904 : :
905 : 0 : kfree(ts);
906 : : }
907 : :
908 : : /*
909 : : * stolen from NFS - maybe should be made a generic function?
910 : : */
911 : 0 : static inline int valid_ipaddr4(const char *buf)
912 : : {
913 : 0 : int rc, count, in[4];
914 : :
915 : 0 : rc = sscanf(buf, "%d.%d.%d.%d", &in[0], &in[1], &in[2], &in[3]);
916 [ # # ]: 0 : if (rc != 4)
917 : : return -EINVAL;
918 [ # # ]: 0 : for (count = 0; count < 4; count++) {
919 [ # # ]: 0 : if (in[count] > 255)
920 : : return -EINVAL;
921 : : }
922 : : return 0;
923 : : }
924 : :
925 : 0 : static int p9_bind_privport(struct socket *sock)
926 : : {
927 : 0 : struct sockaddr_in cl;
928 : 0 : int port, err = -EINVAL;
929 : :
930 : 0 : memset(&cl, 0, sizeof(cl));
931 : 0 : cl.sin_family = AF_INET;
932 : 0 : cl.sin_addr.s_addr = INADDR_ANY;
933 [ # # ]: 0 : for (port = p9_ipport_resv_max; port >= p9_ipport_resv_min; port--) {
934 : 0 : cl.sin_port = htons((ushort)port);
935 : 0 : err = kernel_bind(sock, (struct sockaddr *)&cl, sizeof(cl));
936 [ # # ]: 0 : if (err != -EADDRINUSE)
937 : : break;
938 : : }
939 : 0 : return err;
940 : : }
941 : :
942 : :
943 : : static int
944 : 0 : p9_fd_create_tcp(struct p9_client *client, const char *addr, char *args)
945 : : {
946 : 0 : int err;
947 : 0 : struct socket *csocket;
948 : 0 : struct sockaddr_in sin_server;
949 : 0 : struct p9_fd_opts opts;
950 : :
951 : 0 : err = parse_opts(args, &opts);
952 [ # # ]: 0 : if (err < 0)
953 : : return err;
954 : :
955 [ # # # # ]: 0 : if (addr == NULL || valid_ipaddr4(addr) < 0)
956 : 0 : return -EINVAL;
957 : :
958 : 0 : csocket = NULL;
959 : :
960 : 0 : client->trans_opts.tcp.port = opts.port;
961 : 0 : client->trans_opts.tcp.privport = opts.privport;
962 : 0 : sin_server.sin_family = AF_INET;
963 : 0 : sin_server.sin_addr.s_addr = in_aton(addr);
964 : 0 : sin_server.sin_port = htons(opts.port);
965 : 0 : err = __sock_create(current->nsproxy->net_ns, PF_INET,
966 : : SOCK_STREAM, IPPROTO_TCP, &csocket, 1);
967 [ # # ]: 0 : if (err) {
968 : 0 : pr_err("%s (%d): problem creating socket\n",
969 : : __func__, task_pid_nr(current));
970 : 0 : return err;
971 : : }
972 : :
973 [ # # ]: 0 : if (opts.privport) {
974 : 0 : err = p9_bind_privport(csocket);
975 [ # # ]: 0 : if (err < 0) {
976 : 0 : pr_err("%s (%d): problem binding to privport\n",
977 : : __func__, task_pid_nr(current));
978 : 0 : sock_release(csocket);
979 : 0 : return err;
980 : : }
981 : : }
982 : :
983 : 0 : err = csocket->ops->connect(csocket,
984 : : (struct sockaddr *)&sin_server,
985 : : sizeof(struct sockaddr_in), 0);
986 [ # # ]: 0 : if (err < 0) {
987 : 0 : pr_err("%s (%d): problem connecting socket to %s\n",
988 : : __func__, task_pid_nr(current), addr);
989 : 0 : sock_release(csocket);
990 : 0 : return err;
991 : : }
992 : :
993 : 0 : return p9_socket_open(client, csocket);
994 : : }
995 : :
996 : : static int
997 : 0 : p9_fd_create_unix(struct p9_client *client, const char *addr, char *args)
998 : : {
999 : 0 : int err;
1000 : 0 : struct socket *csocket;
1001 : 0 : struct sockaddr_un sun_server;
1002 : :
1003 : 0 : csocket = NULL;
1004 : :
1005 [ # # ]: 0 : if (addr == NULL)
1006 : : return -EINVAL;
1007 : :
1008 [ # # ]: 0 : if (strlen(addr) >= UNIX_PATH_MAX) {
1009 : 0 : pr_err("%s (%d): address too long: %s\n",
1010 : : __func__, task_pid_nr(current), addr);
1011 : 0 : return -ENAMETOOLONG;
1012 : : }
1013 : :
1014 : 0 : sun_server.sun_family = PF_UNIX;
1015 : 0 : strcpy(sun_server.sun_path, addr);
1016 : 0 : err = __sock_create(current->nsproxy->net_ns, PF_UNIX,
1017 : : SOCK_STREAM, 0, &csocket, 1);
1018 [ # # ]: 0 : if (err < 0) {
1019 : 0 : pr_err("%s (%d): problem creating socket\n",
1020 : : __func__, task_pid_nr(current));
1021 : :
1022 : 0 : return err;
1023 : : }
1024 : 0 : err = csocket->ops->connect(csocket, (struct sockaddr *)&sun_server,
1025 : : sizeof(struct sockaddr_un) - 1, 0);
1026 [ # # ]: 0 : if (err < 0) {
1027 : 0 : pr_err("%s (%d): problem connecting socket: %s: %d\n",
1028 : : __func__, task_pid_nr(current), addr, err);
1029 : 0 : sock_release(csocket);
1030 : 0 : return err;
1031 : : }
1032 : :
1033 : 0 : return p9_socket_open(client, csocket);
1034 : : }
1035 : :
1036 : : static int
1037 : 0 : p9_fd_create(struct p9_client *client, const char *addr, char *args)
1038 : : {
1039 : 0 : int err;
1040 : 0 : struct p9_fd_opts opts;
1041 : :
1042 : 0 : parse_opts(args, &opts);
1043 : 0 : client->trans_opts.fd.rfd = opts.rfd;
1044 : 0 : client->trans_opts.fd.wfd = opts.wfd;
1045 : :
1046 [ # # # # ]: 0 : if (opts.rfd == ~0 || opts.wfd == ~0) {
1047 : 0 : pr_err("Insufficient options for proto=fd\n");
1048 : 0 : return -ENOPROTOOPT;
1049 : : }
1050 : :
1051 : 0 : err = p9_fd_open(client, opts.rfd, opts.wfd);
1052 [ # # ]: 0 : if (err < 0)
1053 : : return err;
1054 : :
1055 : 0 : p9_conn_create(client);
1056 : :
1057 : 0 : return 0;
1058 : : }
1059 : :
1060 : : static struct p9_trans_module p9_tcp_trans = {
1061 : : .name = "tcp",
1062 : : .maxsize = MAX_SOCK_BUF,
1063 : : .def = 0,
1064 : : .create = p9_fd_create_tcp,
1065 : : .close = p9_fd_close,
1066 : : .request = p9_fd_request,
1067 : : .cancel = p9_fd_cancel,
1068 : : .cancelled = p9_fd_cancelled,
1069 : : .show_options = p9_fd_show_options,
1070 : : .owner = THIS_MODULE,
1071 : : };
1072 : :
1073 : : static struct p9_trans_module p9_unix_trans = {
1074 : : .name = "unix",
1075 : : .maxsize = MAX_SOCK_BUF,
1076 : : .def = 0,
1077 : : .create = p9_fd_create_unix,
1078 : : .close = p9_fd_close,
1079 : : .request = p9_fd_request,
1080 : : .cancel = p9_fd_cancel,
1081 : : .cancelled = p9_fd_cancelled,
1082 : : .show_options = p9_fd_show_options,
1083 : : .owner = THIS_MODULE,
1084 : : };
1085 : :
1086 : : static struct p9_trans_module p9_fd_trans = {
1087 : : .name = "fd",
1088 : : .maxsize = MAX_SOCK_BUF,
1089 : : .def = 0,
1090 : : .create = p9_fd_create,
1091 : : .close = p9_fd_close,
1092 : : .request = p9_fd_request,
1093 : : .cancel = p9_fd_cancel,
1094 : : .cancelled = p9_fd_cancelled,
1095 : : .show_options = p9_fd_show_options,
1096 : : .owner = THIS_MODULE,
1097 : : };
1098 : :
1099 : : /**
1100 : : * p9_poll_workfn - poll worker thread
1101 : : * @work: work queue
1102 : : *
1103 : : * polls all v9fs transports for new events and queues the appropriate
1104 : : * work to the work queue
1105 : : *
1106 : : */
1107 : :
1108 : 0 : static void p9_poll_workfn(struct work_struct *work)
1109 : : {
1110 : 0 : unsigned long flags;
1111 : :
1112 : 0 : p9_debug(P9_DEBUG_TRANS, "start %p\n", current);
1113 : :
1114 : 0 : spin_lock_irqsave(&p9_poll_lock, flags);
1115 : 0 : while (!list_empty(&p9_poll_pending_list)) {
1116 : 0 : struct p9_conn *conn = list_first_entry(&p9_poll_pending_list,
1117 : : struct p9_conn,
1118 : : poll_pending_link);
1119 : 0 : list_del_init(&conn->poll_pending_link);
1120 : 0 : spin_unlock_irqrestore(&p9_poll_lock, flags);
1121 : :
1122 : 0 : p9_poll_mux(conn);
1123 : :
1124 [ # # ]: 0 : spin_lock_irqsave(&p9_poll_lock, flags);
1125 : : }
1126 : 0 : spin_unlock_irqrestore(&p9_poll_lock, flags);
1127 : :
1128 : 0 : p9_debug(P9_DEBUG_TRANS, "finish\n");
1129 : 0 : }
1130 : :
1131 : 21 : int p9_trans_fd_init(void)
1132 : : {
1133 : 21 : v9fs_register_trans(&p9_tcp_trans);
1134 : 21 : v9fs_register_trans(&p9_unix_trans);
1135 : 21 : v9fs_register_trans(&p9_fd_trans);
1136 : :
1137 : 21 : return 0;
1138 : : }
1139 : :
1140 : 0 : void p9_trans_fd_exit(void)
1141 : : {
1142 : 0 : flush_work(&p9_poll_work);
1143 : 0 : v9fs_unregister_trans(&p9_tcp_trans);
1144 : 0 : v9fs_unregister_trans(&p9_unix_trans);
1145 : 0 : v9fs_unregister_trans(&p9_fd_trans);
1146 : 0 : }
|