~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/net/9p/trans_fd.c

Version: ~ [ linux-5.15-rc5 ] ~ [ linux-5.14.11 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.72 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.152 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.210 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.250 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.286 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.288 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.18.140 ] ~ [ linux-3.16.85 ] ~ [ linux-3.14.79 ] ~ [ linux-3.12.74 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp