trans_fd.c 31.1 KB
Newer Older
1 2 3 4 5 6 7
/*
 * linux/fs/9p/trans_fd.c
 *
 * Fd transport layer.  Includes deprecated socket layer.
 *
 *  Copyright (C) 2006 by Russ Cox <rsc@swtch.com>
 *  Copyright (C) 2004-2005 by Latchesar Ionkov <lucho@ionkov.net>
8
 *  Copyright (C) 2004-2008 by Eric Van Hensbergen <ericvh@gmail.com>
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
 *  Copyright (C) 1997-2002 by Ron Minnich <rminnich@sarnoff.com>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License version 2
 *  as published by the Free Software Foundation.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to:
 *  Free Software Foundation
 *  51 Franklin Street, Fifth Floor
 *  Boston, MA  02111-1301  USA
 *
 */

#include <linux/in.h>
#include <linux/module.h>
#include <linux/net.h>
#include <linux/ipv6.h>
32
#include <linux/kthread.h>
33 34 35 36 37 38 39
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/un.h>
#include <linux/uaccess.h>
#include <linux/inet.h>
#include <linux/idr.h>
#include <linux/file.h>
E
Eric Van Hensbergen 已提交
40
#include <linux/parser.h>
41
#include <net/9p/9p.h>
42
#include <net/9p/client.h>
43 44 45
#include <net/9p/transport.h>

#define P9_PORT 564
E
Eric Van Hensbergen 已提交
46
#define MAX_SOCK_BUF (64*1024)
47 48
#define ERREQFLUSH	1
#define MAXPOLLWADDR	2
E
Eric Van Hensbergen 已提交
49

E
Eric Van Hensbergen 已提交
50 51 52 53 54 55 56 57
/**
 * struct p9_fd_opts - per-transport options
 * @rfd: file descriptor for reading (trans=fd)
 * @wfd: file descriptor for writing (trans=fd)
 * @port: port to connect to (trans=tcp)
 *
 */

E
Eric Van Hensbergen 已提交
58 59 60 61 62
struct p9_fd_opts {
	int rfd;
	int wfd;
	u16 port;
};
63

E
Eric Van Hensbergen 已提交
64 65 66 67 68 69 70 71
/**
 * struct p9_trans_fd - transport state
 * @rd: reference to file to read from
 * @wr: reference of file to write to
 * @conn: connection state reference
 *
 */

72 73 74
struct p9_trans_fd {
	struct file *rd;
	struct file *wr;
75
	struct p9_conn *conn;
76 77
};

E
Eric Van Hensbergen 已提交
78 79 80 81
/*
  * Option Parsing (code inspired by NFS code)
  *  - a little lazy - parse all fd-transport options
  */
82

E
Eric Van Hensbergen 已提交
83 84
enum {
	/* Options that take integer arguments */
85
	Opt_port, Opt_rfdno, Opt_wfdno, Opt_err,
E
Eric Van Hensbergen 已提交
86
};
87

88
static const match_table_t tokens = {
E
Eric Van Hensbergen 已提交
89 90 91
	{Opt_port, "port=%u"},
	{Opt_rfdno, "rfdno=%u"},
	{Opt_wfdno, "wfdno=%u"},
92
	{Opt_err, NULL},
E
Eric Van Hensbergen 已提交
93
};
94

95 96 97 98 99 100 101 102 103 104 105 106 107 108 109
enum {
	Rworksched = 1,		/* read work scheduled or running */
	Rpending = 2,		/* can read */
	Wworksched = 4,		/* write work scheduled or running */
	Wpending = 8,		/* can write */
};

enum {
	None,
	Flushing,
	Flushed,
};

struct p9_req;
typedef void (*p9_conn_req_callback)(struct p9_req *req, void *a);
E
Eric Van Hensbergen 已提交
110 111 112 113 114 115 116 117 118 119 120 121

/**
 * struct p9_req - fd mux encoding of an rpc transaction
 * @lock: protects req_list
 * @tag: numeric tag for rpc transaction
 * @tcall: request &p9_fcall structure
 * @rcall: response &p9_fcall structure
 * @err: error state
 * @cb: callback for when response is received
 * @cba: argument to pass to callback
 * @flush: flag to indicate RPC has been flushed
 * @req_list: list link for higher level objects to chain requests
122 123
 * @m: connection this request was issued on
 * @wqueue: wait queue that client is blocked on for this rpc
E
Eric Van Hensbergen 已提交
124 125 126
 *
 */

127
struct p9_req {
E
Eric Van Hensbergen 已提交
128
	spinlock_t lock;
129 130 131 132 133 134 135 136
	int tag;
	struct p9_fcall *tcall;
	struct p9_fcall *rcall;
	int err;
	p9_conn_req_callback cb;
	void *cba;
	int flush;
	struct list_head req_list;
137 138
	struct p9_conn *m;
	wait_queue_head_t wqueue;
139 140
};

T
Tejun Heo 已提交
141 142 143 144
struct p9_poll_wait {
	struct p9_conn *conn;
	wait_queue_t wait;
	wait_queue_head_t *wait_addr;
E
Eric Van Hensbergen 已提交
145 146 147 148 149 150
};

/**
 * struct p9_conn - fd mux connection state information
 * @lock: protects mux_list (?)
 * @mux_list: list link for mux to manage multiple connections (?)
151
 * @client: reference to client instance for this connection
E
Eric Van Hensbergen 已提交
152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169
 * @tagpool: id accounting for transactions
 * @err: error state
 * @req_list: accounting for requests which have been sent
 * @unsent_req_list: accounting for requests that haven't been sent
 * @rcall: current response &p9_fcall structure
 * @rpos: read position in current frame
 * @rbuf: current read buffer
 * @wpos: write position for current frame
 * @wsize: amount of data to write for current frame
 * @wbuf: current write buffer
 * @poll_wait: array of wait_q's for various worker threads
 * @poll_waddr: ????
 * @pt: poll state
 * @rq: current read work
 * @wq: current write work
 * @wsched: ????
 *
 */
170 171 172 173

struct p9_conn {
	spinlock_t lock; /* protect lock structure */
	struct list_head mux_list;
174
	struct p9_client *client;
175 176 177 178 179 180 181 182 183 184
	struct p9_idpool *tagpool;
	int err;
	struct list_head req_list;
	struct list_head unsent_req_list;
	struct p9_fcall *rcall;
	int rpos;
	char *rbuf;
	int wpos;
	int wsize;
	char *wbuf;
T
Tejun Heo 已提交
185 186
	struct list_head poll_pending_link;
	struct p9_poll_wait poll_wait[MAXPOLLWADDR];
187 188 189 190 191 192
	poll_table pt;
	struct work_struct rq;
	struct work_struct wq;
	unsigned long wsched;
};

T
Tejun Heo 已提交
193 194
static DEFINE_SPINLOCK(p9_poll_lock);
static LIST_HEAD(p9_poll_pending_list);
195
static struct workqueue_struct *p9_mux_wq;
T
Tejun Heo 已提交
196
static struct task_struct *p9_poll_task;
197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214

static u16 p9_mux_get_tag(struct p9_conn *m)
{
	int tag;

	tag = p9_idpool_get(m->tagpool);
	if (tag < 0)
		return P9_NOTAG;
	else
		return (u16) tag;
}

static void p9_mux_put_tag(struct p9_conn *m, u16 tag)
{
	if (tag != P9_NOTAG && p9_idpool_check(tag, m->tagpool))
		p9_idpool_put(tag, m->tagpool);
}

T
Tejun Heo 已提交
215
static void p9_mux_poll_stop(struct p9_conn *m)
216
{
T
Tejun Heo 已提交
217 218
	unsigned long flags;
	int i;
219

T
Tejun Heo 已提交
220 221
	for (i = 0; i < ARRAY_SIZE(m->poll_wait); i++) {
		struct p9_poll_wait *pwait = &m->poll_wait[i];
222

T
Tejun Heo 已提交
223 224 225
		if (pwait->wait_addr) {
			remove_wait_queue(pwait->wait_addr, &pwait->wait);
			pwait->wait_addr = NULL;
226 227 228
		}
	}

T
Tejun Heo 已提交
229 230 231
	spin_lock_irqsave(&p9_poll_lock, flags);
	list_del_init(&m->poll_pending_link);
	spin_unlock_irqrestore(&p9_poll_lock, flags);
232 233 234
}

/**
235 236 237
 * p9_conn_cancel - cancel all pending requests with error
 * @m: mux data
 * @err: error code
238 239
 *
 */
E
Eric Van Hensbergen 已提交
240

241
void p9_conn_cancel(struct p9_conn *m, int err)
242
{
243 244
	struct p9_req *req, *rtmp;
	LIST_HEAD(cancel_list);
245

246 247 248 249 250 251 252 253
	P9_DPRINTK(P9_DEBUG_ERROR, "mux %p err %d\n", m, err);
	m->err = err;
	spin_lock(&m->lock);
	list_for_each_entry_safe(req, rtmp, &m->req_list, req_list) {
		list_move(&req->req_list, &cancel_list);
	}
	list_for_each_entry_safe(req, rtmp, &m->unsent_req_list, req_list) {
		list_move(&req->req_list, &cancel_list);
254
	}
255
	spin_unlock(&m->lock);
256

257 258 259 260
	list_for_each_entry_safe(req, rtmp, &cancel_list, req_list) {
		list_del(&req->req_list);
		if (!req->err)
			req->err = err;
261

262 263 264 265
		if (req->cb)
			(*req->cb) (req, req->cba);
		else
			kfree(req->rcall);
266
	}
267
}
268

269 270 271 272
static void process_request(struct p9_conn *m, struct p9_req *req)
{
	int ecode;
	struct p9_str *ename;
273

274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291
	if (!req->err && req->rcall->id == P9_RERROR) {
		ecode = req->rcall->params.rerror.errno;
		ename = &req->rcall->params.rerror.error;

		P9_DPRINTK(P9_DEBUG_MUX, "Rerror %.*s\n", ename->len,
								ename->str);

		if (m->client->dotu)
			req->err = -ecode;

		if (!req->err) {
			req->err = p9_errstr2errno(ename->str, ename->len);

			/* string match failed */
			if (!req->err) {
				PRINT_FCALL_ERROR("unknown error", req->rcall);
				req->err = -ESERVERFAULT;
			}
292
		}
293 294 295 296 297 298
	} else if (req->tcall && req->rcall->id != req->tcall->id + 1) {
		P9_DPRINTK(P9_DEBUG_ERROR,
				"fcall mismatch: expected %d, got %d\n",
				req->tcall->id + 1, req->rcall->id);
		if (!req->err)
			req->err = -EIO;
299 300 301
	}
}

302 303
static unsigned int
p9_fd_poll(struct p9_client *client, struct poll_table_struct *pt)
304
{
305 306
	int ret, n;
	struct p9_trans_fd *ts = NULL;
307

308 309
	if (client && client->status == Connected)
		ts = client->trans;
310

311 312
	if (!ts)
		return -EREMOTEIO;
313

314 315
	if (!ts->rd->f_op || !ts->rd->f_op->poll)
		return -EIO;
316

317 318
	if (!ts->wr->f_op || !ts->wr->f_op->poll)
		return -EIO;
T
Tejun Heo 已提交
319

320 321 322
	ret = ts->rd->f_op->poll(ts->rd, pt);
	if (ret < 0)
		return ret;
T
Tejun Heo 已提交
323

324 325 326 327 328 329 330 331
	if (ts->rd != ts->wr) {
		n = ts->wr->f_op->poll(ts->wr, pt);
		if (n < 0)
			return n;
		ret = (ret & ~POLLOUT) | (n & ~POLLIN);
	}

	return ret;
T
Tejun Heo 已提交
332 333
}

334
/**
335 336 337 338
 * p9_fd_read- read from a fd
 * @client: client instance
 * @v: buffer to receive data into
 * @len: size of receive buffer
E
Eric Van Hensbergen 已提交
339
 *
340
 */
E
Eric Van Hensbergen 已提交
341

342
static int p9_fd_read(struct p9_client *client, void *v, int len)
343
{
344 345
	int ret;
	struct p9_trans_fd *ts = NULL;
346

347 348
	if (client && client->status != Disconnected)
		ts = client->trans;
349

350 351
	if (!ts)
		return -EREMOTEIO;
352

353 354
	if (!(ts->rd->f_flags & O_NONBLOCK))
		P9_DPRINTK(P9_DEBUG_ERROR, "blocking read ...\n");
355

356 357 358 359
	ret = kernel_read(ts->rd, ts->rd->f_pos, v, len);
	if (ret <= 0 && ret != -ERESTARTSYS && ret != -EAGAIN)
		client->status = Disconnected;
	return ret;
360 361 362
}

/**
363 364
 * p9_read_work - called when there is some data to be read from a transport
 * @work: container of work to be done
E
Eric Van Hensbergen 已提交
365
 *
366
 */
E
Eric Van Hensbergen 已提交
367

368
static void p9_read_work(struct work_struct *work)
369
{
370 371 372 373 374 375 376
	int n, err;
	struct p9_conn *m;
	struct p9_req *req, *rptr, *rreq;
	struct p9_fcall *rcall;
	char *rbuf;

	m = container_of(work, struct p9_conn, rq);
377 378 379 380

	if (m->err < 0)
		return;

381 382
	rcall = NULL;
	P9_DPRINTK(P9_DEBUG_MUX, "start mux %p pos %d\n", m, m->rpos);
383

384 385 386 387 388 389 390
	if (!m->rcall) {
		m->rcall =
		    kmalloc(sizeof(struct p9_fcall) + m->client->msize,
								GFP_KERNEL);
		if (!m->rcall) {
			err = -ENOMEM;
			goto error;
391
		}
392 393 394

		m->rbuf = (char *)m->rcall + sizeof(struct p9_fcall);
		m->rpos = 0;
395 396
	}

397 398 399 400 401 402 403
	clear_bit(Rpending, &m->wsched);
	err = p9_fd_read(m->client, m->rbuf + m->rpos,
						m->client->msize - m->rpos);
	P9_DPRINTK(P9_DEBUG_MUX, "mux %p got %d bytes\n", m, err);
	if (err == -EAGAIN) {
		clear_bit(Rworksched, &m->wsched);
		return;
404 405
	}

406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515
	if (err <= 0)
		goto error;

	m->rpos += err;
	while (m->rpos > 4) {
		n = le32_to_cpu(*(__le32 *) m->rbuf);
		if (n >= m->client->msize) {
			P9_DPRINTK(P9_DEBUG_ERROR,
				"requested packet size too big: %d\n", n);
			err = -EIO;
			goto error;
		}

		if (m->rpos < n)
			break;

		err =
		    p9_deserialize_fcall(m->rbuf, n, m->rcall, m->client->dotu);
		if (err < 0)
			goto error;

#ifdef CONFIG_NET_9P_DEBUG
		if ((p9_debug_level&P9_DEBUG_FCALL) == P9_DEBUG_FCALL) {
			char buf[150];

			p9_printfcall(buf, sizeof(buf), m->rcall,
				m->client->dotu);
			printk(KERN_NOTICE ">>> %p %s\n", m, buf);
		}
#endif

		rcall = m->rcall;
		rbuf = m->rbuf;
		if (m->rpos > n) {
			m->rcall = kmalloc(sizeof(struct p9_fcall) +
						m->client->msize, GFP_KERNEL);
			if (!m->rcall) {
				err = -ENOMEM;
				goto error;
			}

			m->rbuf = (char *)m->rcall + sizeof(struct p9_fcall);
			memmove(m->rbuf, rbuf + n, m->rpos - n);
			m->rpos -= n;
		} else {
			m->rcall = NULL;
			m->rbuf = NULL;
			m->rpos = 0;
		}

		P9_DPRINTK(P9_DEBUG_MUX, "mux %p fcall id %d tag %d\n", m,
							rcall->id, rcall->tag);

		req = NULL;
		spin_lock(&m->lock);
		list_for_each_entry_safe(rreq, rptr, &m->req_list, req_list) {
			if (rreq->tag == rcall->tag) {
				req = rreq;
				if (req->flush != Flushing)
					list_del(&req->req_list);
				break;
			}
		}
		spin_unlock(&m->lock);

		if (req) {
			req->rcall = rcall;
			process_request(m, req);

			if (req->flush != Flushing) {
				if (req->cb)
					(*req->cb) (req, req->cba);
				else
					kfree(req->rcall);
			}
		} else {
			if (err >= 0 && rcall->id != P9_RFLUSH)
				P9_DPRINTK(P9_DEBUG_ERROR,
				  "unexpected response mux %p id %d tag %d\n",
				  m, rcall->id, rcall->tag);
			kfree(rcall);
		}
	}

	if (!list_empty(&m->req_list)) {
		if (test_and_clear_bit(Rpending, &m->wsched))
			n = POLLIN;
		else
			n = p9_fd_poll(m->client, NULL);

		if (n & POLLIN) {
			P9_DPRINTK(P9_DEBUG_MUX, "schedule read work %p\n", m);
			queue_work(p9_mux_wq, &m->rq);
		} else
			clear_bit(Rworksched, &m->wsched);
	} else
		clear_bit(Rworksched, &m->wsched);

	return;

error:
	p9_conn_cancel(m, err);
	clear_bit(Rworksched, &m->wsched);
}

/**
 * p9_fd_write - write to a socket
 * @client: client instance
 * @v: buffer to send data from
 * @len: size of send buffer
E
Eric Van Hensbergen 已提交
516
 *
517
 */
E
Eric Van Hensbergen 已提交
518

519
static int p9_fd_write(struct p9_client *client, void *v, int len)
520
{
521 522 523
	int ret;
	mm_segment_t oldfs;
	struct p9_trans_fd *ts = NULL;
524

525 526
	if (client && client->status != Disconnected)
		ts = client->trans;
527

528 529
	if (!ts)
		return -EREMOTEIO;
530

531 532
	if (!(ts->wr->f_flags & O_NONBLOCK))
		P9_DPRINTK(P9_DEBUG_ERROR, "blocking write ...\n");
T
Tejun Heo 已提交
533

534 535 536 537 538
	oldfs = get_fs();
	set_fs(get_ds());
	/* The cast to a user pointer is valid due to the set_fs() */
	ret = vfs_write(ts->wr, (void __user *)v, len, &ts->wr->f_pos);
	set_fs(oldfs);
T
Tejun Heo 已提交
539

540 541 542
	if (ret <= 0 && ret != -ERESTARTSYS && ret != -EAGAIN)
		client->status = Disconnected;
	return ret;
543 544 545 546
}

/**
 * p9_write_work - called when a transport can send some data
E
Eric Van Hensbergen 已提交
547 548
 * @work: container for work to be done
 *
549
 */
E
Eric Van Hensbergen 已提交
550

551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586
static void p9_write_work(struct work_struct *work)
{
	int n, err;
	struct p9_conn *m;
	struct p9_req *req;

	m = container_of(work, struct p9_conn, wq);

	if (m->err < 0) {
		clear_bit(Wworksched, &m->wsched);
		return;
	}

	if (!m->wsize) {
		if (list_empty(&m->unsent_req_list)) {
			clear_bit(Wworksched, &m->wsched);
			return;
		}

		spin_lock(&m->lock);
again:
		req = list_entry(m->unsent_req_list.next, struct p9_req,
			       req_list);
		list_move_tail(&req->req_list, &m->req_list);
		if (req->err == ERREQFLUSH)
			goto again;

		m->wbuf = req->tcall->sdata;
		m->wsize = req->tcall->size;
		m->wpos = 0;
		spin_unlock(&m->lock);
	}

	P9_DPRINTK(P9_DEBUG_MUX, "mux %p pos %d size %d\n", m, m->wpos,
								m->wsize);
	clear_bit(Wpending, &m->wsched);
587
	err = p9_fd_write(m->client, m->wbuf + m->wpos, m->wsize - m->wpos);
588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608
	P9_DPRINTK(P9_DEBUG_MUX, "mux %p sent %d bytes\n", m, err);
	if (err == -EAGAIN) {
		clear_bit(Wworksched, &m->wsched);
		return;
	}

	if (err < 0)
		goto error;
	else if (err == 0) {
		err = -EREMOTEIO;
		goto error;
	}

	m->wpos += err;
	if (m->wpos == m->wsize)
		m->wpos = m->wsize = 0;

	if (m->wsize == 0 && !list_empty(&m->unsent_req_list)) {
		if (test_and_clear_bit(Wpending, &m->wsched))
			n = POLLOUT;
		else
609
			n = p9_fd_poll(m->client, NULL);
610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625

		if (n & POLLOUT) {
			P9_DPRINTK(P9_DEBUG_MUX, "schedule write work %p\n", m);
			queue_work(p9_mux_wq, &m->wq);
		} else
			clear_bit(Wworksched, &m->wsched);
	} else
		clear_bit(Wworksched, &m->wsched);

	return;

error:
	p9_conn_cancel(m, err);
	clear_bit(Wworksched, &m->wsched);
}

626
static int p9_pollwake(wait_queue_t *wait, unsigned mode, int sync, void *key)
627
{
628 629 630 631 632
	struct p9_poll_wait *pwait =
		container_of(wait, struct p9_poll_wait, wait);
	struct p9_conn *m = pwait->conn;
	unsigned long flags;
	DECLARE_WAITQUEUE(dummy_wait, p9_poll_task);
633

634 635 636 637
	spin_lock_irqsave(&p9_poll_lock, flags);
	if (list_empty(&m->poll_pending_link))
		list_add_tail(&m->poll_pending_link, &p9_poll_pending_list);
	spin_unlock_irqrestore(&p9_poll_lock, flags);
638

639 640
	/* perform the default wake up operation */
	return default_wake_function(&dummy_wait, mode, sync, key);
641 642 643
}

/**
644 645 646 647
 * p9_pollwait - add poll task to the wait queue
 * @filp: file pointer being polled
 * @wait_address: wait_q to block on
 * @p: poll state
E
Eric Van Hensbergen 已提交
648
 *
649
 * called by files poll operation to add v9fs-poll task to files wait queue
650
 */
E
Eric Van Hensbergen 已提交
651

652 653
static void
p9_pollwait(struct file *filp, wait_queue_head_t *wait_address, poll_table *p)
654
{
655 656 657
	struct p9_conn *m = container_of(p, struct p9_conn, pt);
	struct p9_poll_wait *pwait = NULL;
	int i;
658

659 660 661 662
	for (i = 0; i < ARRAY_SIZE(m->poll_wait); i++) {
		if (m->poll_wait[i].wait_addr == NULL) {
			pwait = &m->poll_wait[i];
			break;
663 664 665
		}
	}

666 667
	if (!pwait) {
		P9_DPRINTK(P9_DEBUG_ERROR, "not enough wait_address slots\n");
668 669 670
		return;
	}

671 672 673 674 675
	if (!wait_address) {
		P9_DPRINTK(P9_DEBUG_ERROR, "no wait_address\n");
		pwait->wait_addr = ERR_PTR(-EIO);
		return;
	}
676

677 678 679 680 681
	pwait->conn = m;
	pwait->wait_addr = wait_address;
	init_waitqueue_func_entry(&pwait->wait, p9_pollwake);
	add_wait_queue(wait_address, &pwait->wait);
}
682

683 684 685 686 687 688
/**
 * p9_conn_create - allocate and initialize the per-session mux data
 * @client: client instance
 *
 * Note: Creates the polling task if this is the first session.
 */
689

690 691 692 693
static struct p9_conn *p9_conn_create(struct p9_client *client)
{
	int i, n;
	struct p9_conn *m;
694

695 696 697 698
	P9_DPRINTK(P9_DEBUG_MUX, "client %p msize %d\n", client, client->msize);
	m = kzalloc(sizeof(struct p9_conn), GFP_KERNEL);
	if (!m)
		return ERR_PTR(-ENOMEM);
699

700 701 702 703 704 705 706 707
	spin_lock_init(&m->lock);
	INIT_LIST_HEAD(&m->mux_list);
	m->client = client;
	m->tagpool = p9_idpool_create();
	if (IS_ERR(m->tagpool)) {
		kfree(m);
		return ERR_PTR(-ENOMEM);
	}
708

709 710 711 712 713 714
	INIT_LIST_HEAD(&m->req_list);
	INIT_LIST_HEAD(&m->unsent_req_list);
	INIT_WORK(&m->rq, p9_read_work);
	INIT_WORK(&m->wq, p9_write_work);
	INIT_LIST_HEAD(&m->poll_pending_link);
	init_poll_funcptr(&m->pt, p9_pollwait);
715

716 717 718 719 720
	n = p9_fd_poll(client, &m->pt);
	if (n & POLLIN) {
		P9_DPRINTK(P9_DEBUG_MUX, "mux %p can read\n", m);
		set_bit(Rpending, &m->wsched);
	}
721

722 723 724 725 726 727 728 729 730 731 732
	if (n & POLLOUT) {
		P9_DPRINTK(P9_DEBUG_MUX, "mux %p can write\n", m);
		set_bit(Wpending, &m->wsched);
	}

	for (i = 0; i < ARRAY_SIZE(m->poll_wait); i++) {
		if (IS_ERR(m->poll_wait[i].wait_addr)) {
			p9_mux_poll_stop(m);
			kfree(m);
			/* return the error code */
			return (void *)m->poll_wait[i].wait_addr;
733 734 735
		}
	}

736 737
	return m;
}
738

739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763
/**
 * p9_poll_mux - polls a mux and schedules read or write works if necessary
 * @m: connection to poll
 *
 */

static void p9_poll_mux(struct p9_conn *m)
{
	int n;

	if (m->err < 0)
		return;

	n = p9_fd_poll(m->client, NULL);
	if (n < 0 || n & (POLLERR | POLLHUP | POLLNVAL)) {
		P9_DPRINTK(P9_DEBUG_MUX, "error mux %p err %d\n", m, n);
		if (n >= 0)
			n = -ECONNRESET;
		p9_conn_cancel(m, n);
	}

	if (n & POLLIN) {
		set_bit(Rpending, &m->wsched);
		P9_DPRINTK(P9_DEBUG_MUX, "mux %p can read\n", m);
		if (!test_and_set_bit(Rworksched, &m->wsched)) {
764 765
			P9_DPRINTK(P9_DEBUG_MUX, "schedule read work %p\n", m);
			queue_work(p9_mux_wq, &m->rq);
766 767
		}
	}
768

769 770 771 772 773 774 775 776 777
	if (n & POLLOUT) {
		set_bit(Wpending, &m->wsched);
		P9_DPRINTK(P9_DEBUG_MUX, "mux %p can write\n", m);
		if ((m->wsize || !list_empty(&m->unsent_req_list))
		    && !test_and_set_bit(Wworksched, &m->wsched)) {
			P9_DPRINTK(P9_DEBUG_MUX, "schedule write work %p\n", m);
			queue_work(p9_mux_wq, &m->wq);
		}
	}
778 779 780 781 782 783 784 785 786 787 788 789 790
}

/**
 * p9_send_request - send 9P request
 * The function can sleep until the request is scheduled for sending.
 * The function can be interrupted. Return from the function is not
 * a guarantee that the request is sent successfully. Can return errors
 * that can be retrieved by PTR_ERR macros.
 *
 * @m: mux data
 * @tc: request to be sent
 * @cb: callback function to call when response is received
 * @cba: parameter to pass to the callback function
E
Eric Van Hensbergen 已提交
791
 *
792
 */
E
Eric Van Hensbergen 已提交
793

794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814
static struct p9_req *p9_send_request(struct p9_conn *m,
					  struct p9_fcall *tc,
					  p9_conn_req_callback cb, void *cba)
{
	int n;
	struct p9_req *req;

	P9_DPRINTK(P9_DEBUG_MUX, "mux %p task %p tcall %p id %d\n", m, current,
		tc, tc->id);
	if (m->err < 0)
		return ERR_PTR(m->err);

	req = kmalloc(sizeof(struct p9_req), GFP_KERNEL);
	if (!req)
		return ERR_PTR(-ENOMEM);

	if (tc->id == P9_TVERSION)
		n = P9_NOTAG;
	else
		n = p9_mux_get_tag(m);

J
Julia Lawall 已提交
815 816
	if (n < 0) {
		kfree(req);
817
		return ERR_PTR(-ENOMEM);
J
Julia Lawall 已提交
818
	}
819 820 821 822 823 824 825

	p9_set_tag(tc, n);

#ifdef CONFIG_NET_9P_DEBUG
	if ((p9_debug_level&P9_DEBUG_FCALL) == P9_DEBUG_FCALL) {
		char buf[150];

826
		p9_printfcall(buf, sizeof(buf), tc, m->client->dotu);
827 828 829 830 831
		printk(KERN_NOTICE "<<< %p %s\n", m, buf);
	}
#endif

	spin_lock_init(&req->lock);
832 833
	req->m = m;
	init_waitqueue_head(&req->wqueue);
834 835 836 837 838 839 840 841 842 843 844 845 846 847 848
	req->tag = n;
	req->tcall = tc;
	req->rcall = NULL;
	req->err = 0;
	req->cb = cb;
	req->cba = cba;
	req->flush = None;

	spin_lock(&m->lock);
	list_add_tail(&req->req_list, &m->unsent_req_list);
	spin_unlock(&m->lock);

	if (test_and_clear_bit(Wpending, &m->wsched))
		n = POLLOUT;
	else
849
		n = p9_fd_poll(m->client, NULL);
850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943

	if (n & POLLOUT && !test_and_set_bit(Wworksched, &m->wsched))
		queue_work(p9_mux_wq, &m->wq);

	return req;
}

static void p9_mux_free_request(struct p9_conn *m, struct p9_req *req)
{
	p9_mux_put_tag(m, req->tag);
	kfree(req);
}

static void p9_mux_flush_cb(struct p9_req *freq, void *a)
{
	int tag;
	struct p9_conn *m;
	struct p9_req *req, *rreq, *rptr;

	m = a;
	P9_DPRINTK(P9_DEBUG_MUX, "mux %p tc %p rc %p err %d oldtag %d\n", m,
		freq->tcall, freq->rcall, freq->err,
		freq->tcall->params.tflush.oldtag);

	spin_lock(&m->lock);
	tag = freq->tcall->params.tflush.oldtag;
	req = NULL;
	list_for_each_entry_safe(rreq, rptr, &m->req_list, req_list) {
		if (rreq->tag == tag) {
			req = rreq;
			list_del(&req->req_list);
			break;
		}
	}
	spin_unlock(&m->lock);

	if (req) {
		spin_lock(&req->lock);
		req->flush = Flushed;
		spin_unlock(&req->lock);

		if (req->cb)
			(*req->cb) (req, req->cba);
		else
			kfree(req->rcall);
	}

	kfree(freq->tcall);
	kfree(freq->rcall);
	p9_mux_free_request(m, freq);
}

static int
p9_mux_flush_request(struct p9_conn *m, struct p9_req *req)
{
	struct p9_fcall *fc;
	struct p9_req *rreq, *rptr;

	P9_DPRINTK(P9_DEBUG_MUX, "mux %p req %p tag %d\n", m, req, req->tag);

	/* if a response was received for a request, do nothing */
	spin_lock(&req->lock);
	if (req->rcall || req->err) {
		spin_unlock(&req->lock);
		P9_DPRINTK(P9_DEBUG_MUX,
			"mux %p req %p response already received\n", m, req);
		return 0;
	}

	req->flush = Flushing;
	spin_unlock(&req->lock);

	spin_lock(&m->lock);
	/* if the request is not sent yet, just remove it from the list */
	list_for_each_entry_safe(rreq, rptr, &m->unsent_req_list, req_list) {
		if (rreq->tag == req->tag) {
			P9_DPRINTK(P9_DEBUG_MUX,
			   "mux %p req %p request is not sent yet\n", m, req);
			list_del(&rreq->req_list);
			req->flush = Flushed;
			spin_unlock(&m->lock);
			if (req->cb)
				(*req->cb) (req, req->cba);
			return 0;
		}
	}
	spin_unlock(&m->lock);

	clear_thread_flag(TIF_SIGPENDING);
	fc = p9_create_tflush(req->tag);
	p9_send_request(m, fc, p9_mux_flush_cb, m);
	return 1;
}

944
static void p9_conn_rpc_cb(struct p9_req *req, void *a)
945
{
946
	P9_DPRINTK(P9_DEBUG_MUX, "req %p arg %p\n", req, a);
947 948

	if (req->flush != None && !req->err)
949
		req->err = -ERESTARTSYS;
950

951
	wake_up(&req->wqueue);
952 953 954 955 956
}

/**
 * p9_fd_rpc- sends 9P request and waits until a response is available.
 *	The function can be interrupted.
957
 * @client: client instance
958 959
 * @tc: request to be sent
 * @rc: pointer where a pointer to the response is stored
E
Eric Van Hensbergen 已提交
960
 *
961
 */
E
Eric Van Hensbergen 已提交
962

963
int
964
p9_fd_rpc(struct p9_client *client, struct p9_fcall *tc, struct p9_fcall **rc)
965
{
966
	struct p9_trans_fd *p = client->trans;
967 968 969 970 971 972 973 974 975 976 977 978 979 980
	struct p9_conn *m = p->conn;
	int err, sigpending;
	unsigned long flags;
	struct p9_req *req;

	if (rc)
		*rc = NULL;

	sigpending = 0;
	if (signal_pending(current)) {
		sigpending = 1;
		clear_thread_flag(TIF_SIGPENDING);
	}

981
	req = p9_send_request(m, tc, p9_conn_rpc_cb, NULL);
982 983 984 985 986 987
	if (IS_ERR(req)) {
		err = PTR_ERR(req);
		P9_DPRINTK(P9_DEBUG_MUX, "error %d\n", err);
		return err;
	}

988 989 990 991
	err = wait_event_interruptible(req->wqueue, req->rcall != NULL ||
								req->err < 0);
	if (req->err < 0)
		err = req->err;
992

993
	if (err == -ERESTARTSYS && client->status == Connected
994 995 996 997 998
							&& m->err == 0) {
		if (p9_mux_flush_request(m, req)) {
			/* wait until we get response of the flush message */
			do {
				clear_thread_flag(TIF_SIGPENDING);
999 1000 1001 1002 1003
				err = wait_event_interruptible(req->wqueue,
					req->rcall || req->err);
			} while (!req->rcall && !req->err &&
					err == -ERESTARTSYS &&
					client->status == Connected && !m->err);
1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016

			err = -ERESTARTSYS;
		}
		sigpending = 1;
	}

	if (sigpending) {
		spin_lock_irqsave(&current->sighand->siglock, flags);
		recalc_sigpending();
		spin_unlock_irqrestore(&current->sighand->siglock, flags);
	}

	if (rc)
1017
		*rc = req->rcall;
1018
	else
1019
		kfree(req->rcall);
1020 1021 1022 1023 1024 1025 1026 1027

	p9_mux_free_request(m, req);
	if (err > 0)
		err = -EIO;

	return err;
}

E
Eric Van Hensbergen 已提交
1028
/**
1029
 * parse_options - parse mount options into session structure
E
Eric Van Hensbergen 已提交
1030
 * @options: options string passed from mount
E
Eric Van Hensbergen 已提交
1031
 * @opts: transport-specific structure to parse options into
E
Eric Van Hensbergen 已提交
1032
 *
1033
 * Returns 0 upon success, -ERRNO upon failure
E
Eric Van Hensbergen 已提交
1034
 */
1035

1036
static int parse_opts(char *params, struct p9_fd_opts *opts)
1037
{
E
Eric Van Hensbergen 已提交
1038 1039 1040
	char *p;
	substring_t args[MAX_OPT_ARGS];
	int option;
1041
	char *options;
E
Eric Van Hensbergen 已提交
1042
	int ret;
1043

E
Eric Van Hensbergen 已提交
1044 1045 1046
	opts->port = P9_PORT;
	opts->rfd = ~0;
	opts->wfd = ~0;
1047

1048 1049 1050 1051 1052 1053 1054 1055 1056
	if (!params)
		return 0;

	options = kstrdup(params, GFP_KERNEL);
	if (!options) {
		P9_DPRINTK(P9_DEBUG_ERROR,
				"failed to allocate copy of option string\n");
		return -ENOMEM;
	}
1057

E
Eric Van Hensbergen 已提交
1058 1059
	while ((p = strsep(&options, ",")) != NULL) {
		int token;
1060
		int r;
E
Eric Van Hensbergen 已提交
1061 1062 1063
		if (!*p)
			continue;
		token = match_token(p, tokens, args);
1064 1065
		r = match_int(&args[0], &option);
		if (r < 0) {
E
Eric Van Hensbergen 已提交
1066 1067
			P9_DPRINTK(P9_DEBUG_ERROR,
			 "integer field, but no integer?\n");
1068
			ret = r;
E
Eric Van Hensbergen 已提交
1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083
			continue;
		}
		switch (token) {
		case Opt_port:
			opts->port = option;
			break;
		case Opt_rfdno:
			opts->rfd = option;
			break;
		case Opt_wfdno:
			opts->wfd = option;
			break;
		default:
			continue;
		}
1084
	}
1085 1086
	kfree(options);
	return 0;
1087 1088
}

1089
static int p9_fd_open(struct p9_client *client, int rfd, int wfd)
1090
{
E
Eric Van Hensbergen 已提交
1091 1092 1093 1094
	struct p9_trans_fd *ts = kmalloc(sizeof(struct p9_trans_fd),
					   GFP_KERNEL);
	if (!ts)
		return -ENOMEM;
1095

E
Eric Van Hensbergen 已提交
1096 1097 1098 1099 1100 1101 1102 1103 1104
	ts->rd = fget(rfd);
	ts->wr = fget(wfd);
	if (!ts->rd || !ts->wr) {
		if (ts->rd)
			fput(ts->rd);
		if (ts->wr)
			fput(ts->wr);
		kfree(ts);
		return -EIO;
1105 1106
	}

1107 1108
	client->trans = ts;
	client->status = Connected;
1109

E
Eric Van Hensbergen 已提交
1110
	return 0;
1111 1112
}

1113
static int p9_socket_open(struct p9_client *client, struct socket *csocket)
1114 1115 1116 1117
{
	int fd, ret;

	csocket->sk->sk_allocation = GFP_NOIO;
1118
	fd = sock_map_fd(csocket, 0);
1119 1120 1121 1122 1123
	if (fd < 0) {
		P9_EPRINTK(KERN_ERR, "p9_socket_open: failed to map fd\n");
		return fd;
	}

1124
	ret = p9_fd_open(client, fd, fd);
1125 1126 1127 1128 1129 1130
	if (ret < 0) {
		P9_EPRINTK(KERN_ERR, "p9_socket_open: failed to open fd\n");
		sockfd_put(csocket);
		return ret;
	}

1131
	((struct p9_trans_fd *)client->trans)->rd->f_flags |= O_NONBLOCK;
1132 1133 1134 1135 1136

	return 0;
}

/**
1137 1138
 * p9_mux_destroy - cancels all pending requests and frees mux resources
 * @m: mux to destroy
1139 1140
 *
 */
E
Eric Van Hensbergen 已提交
1141

1142
static void p9_conn_destroy(struct p9_conn *m)
1143
{
1144 1145
	P9_DPRINTK(P9_DEBUG_MUX, "mux %p prev %p next %p\n", m,
		m->mux_list.prev, m->mux_list.next);
1146

1147 1148 1149
	p9_mux_poll_stop(m);
	cancel_work_sync(&m->rq);
	cancel_work_sync(&m->wq);
1150

1151
	p9_conn_cancel(m, -ECONNRESET);
1152

1153 1154 1155
	m->client = NULL;
	p9_idpool_destroy(m->tagpool);
	kfree(m);
1156 1157 1158
}

/**
1159 1160
 * p9_fd_close - shutdown file descriptor transport
 * @client: client instance
1161 1162
 *
 */
E
Eric Van Hensbergen 已提交
1163

1164
static void p9_fd_close(struct p9_client *client)
1165 1166 1167
{
	struct p9_trans_fd *ts;

1168
	if (!client)
1169 1170
		return;

1171
	ts = client->trans;
1172 1173 1174
	if (!ts)
		return;

1175 1176
	client->status = Disconnected;

1177 1178
	p9_conn_destroy(ts->conn);

1179 1180 1181 1182
	if (ts->rd)
		fput(ts->rd);
	if (ts->wr)
		fput(ts->wr);
1183

1184 1185 1186
	kfree(ts);
}

1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203
/*
 * stolen from NFS - maybe should be made a generic function?
 */
static inline int valid_ipaddr4(const char *buf)
{
	int rc, count, in[4];

	rc = sscanf(buf, "%d.%d.%d.%d", &in[0], &in[1], &in[2], &in[3]);
	if (rc != 4)
		return -EINVAL;
	for (count = 0; count < 4; count++) {
		if (in[count] > 255)
			return -EINVAL;
	}
	return 0;
}

1204 1205
static int
p9_fd_create_tcp(struct p9_client *client, const char *addr, char *args)
E
Eric Van Hensbergen 已提交
1206 1207 1208 1209 1210
{
	int err;
	struct socket *csocket;
	struct sockaddr_in sin_server;
	struct p9_fd_opts opts;
1211
	struct p9_trans_fd *p = NULL; /* this gets allocated in p9_fd_open */
E
Eric Van Hensbergen 已提交
1212

1213 1214
	err = parse_opts(args, &opts);
	if (err < 0)
1215
		return err;
E
Eric Van Hensbergen 已提交
1216

1217
	if (valid_ipaddr4(addr) < 0)
1218
		return -EINVAL;
1219

E
Eric Van Hensbergen 已提交
1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242
	csocket = NULL;

	sin_server.sin_family = AF_INET;
	sin_server.sin_addr.s_addr = in_aton(addr);
	sin_server.sin_port = htons(opts.port);
	sock_create_kern(PF_INET, SOCK_STREAM, IPPROTO_TCP, &csocket);

	if (!csocket) {
		P9_EPRINTK(KERN_ERR, "p9_trans_tcp: problem creating socket\n");
		err = -EIO;
		goto error;
	}

	err = csocket->ops->connect(csocket,
				    (struct sockaddr *)&sin_server,
				    sizeof(struct sockaddr_in), 0);
	if (err < 0) {
		P9_EPRINTK(KERN_ERR,
			"p9_trans_tcp: problem connecting socket to %s\n",
			addr);
		goto error;
	}

1243
	err = p9_socket_open(client, csocket);
E
Eric Van Hensbergen 已提交
1244 1245 1246
	if (err < 0)
		goto error;

1247 1248
	p = (struct p9_trans_fd *) client->trans;
	p->conn = p9_conn_create(client);
1249 1250 1251 1252 1253 1254
	if (IS_ERR(p->conn)) {
		err = PTR_ERR(p->conn);
		p->conn = NULL;
		goto error;
	}

1255
	return 0;
E
Eric Van Hensbergen 已提交
1256 1257 1258 1259 1260

error:
	if (csocket)
		sock_release(csocket);

1261 1262 1263
	kfree(p);

	return err;
E
Eric Van Hensbergen 已提交
1264 1265
}

1266 1267
static int
p9_fd_create_unix(struct p9_client *client, const char *addr, char *args)
E
Eric Van Hensbergen 已提交
1268 1269 1270 1271
{
	int err;
	struct socket *csocket;
	struct sockaddr_un sun_server;
1272
	struct p9_trans_fd *p = NULL; /* this gets allocated in p9_fd_open */
E
Eric Van Hensbergen 已提交
1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294

	csocket = NULL;

	if (strlen(addr) > UNIX_PATH_MAX) {
		P9_EPRINTK(KERN_ERR, "p9_trans_unix: address too long: %s\n",
			addr);
		err = -ENAMETOOLONG;
		goto error;
	}

	sun_server.sun_family = PF_UNIX;
	strcpy(sun_server.sun_path, addr);
	sock_create_kern(PF_UNIX, SOCK_STREAM, 0, &csocket);
	err = csocket->ops->connect(csocket, (struct sockaddr *)&sun_server,
			sizeof(struct sockaddr_un) - 1, 0);
	if (err < 0) {
		P9_EPRINTK(KERN_ERR,
			"p9_trans_unix: problem connecting socket: %s: %d\n",
			addr, err);
		goto error;
	}

1295
	err = p9_socket_open(client, csocket);
E
Eric Van Hensbergen 已提交
1296 1297 1298
	if (err < 0)
		goto error;

1299 1300
	p = (struct p9_trans_fd *) client->trans;
	p->conn = p9_conn_create(client);
1301 1302 1303 1304 1305 1306
	if (IS_ERR(p->conn)) {
		err = PTR_ERR(p->conn);
		p->conn = NULL;
		goto error;
	}

1307
	return 0;
E
Eric Van Hensbergen 已提交
1308 1309 1310 1311 1312

error:
	if (csocket)
		sock_release(csocket);

1313 1314
	kfree(p);
	return err;
E
Eric Van Hensbergen 已提交
1315 1316
}

1317 1318
static int
p9_fd_create(struct p9_client *client, const char *addr, char *args)
E
Eric Van Hensbergen 已提交
1319 1320 1321
{
	int err;
	struct p9_fd_opts opts;
1322
	struct p9_trans_fd *p = NULL; /* this get allocated in p9_fd_open */
E
Eric Van Hensbergen 已提交
1323 1324 1325 1326 1327

	parse_opts(args, &opts);

	if (opts.rfd == ~0 || opts.wfd == ~0) {
		printk(KERN_ERR "v9fs: Insufficient options for proto=fd\n");
1328
		return -ENOPROTOOPT;
E
Eric Van Hensbergen 已提交
1329 1330
	}

1331
	err = p9_fd_open(client, opts.rfd, opts.wfd);
E
Eric Van Hensbergen 已提交
1332 1333 1334
	if (err < 0)
		goto error;

1335 1336
	p = (struct p9_trans_fd *) client->trans;
	p->conn = p9_conn_create(client);
1337 1338 1339 1340 1341 1342
	if (IS_ERR(p->conn)) {
		err = PTR_ERR(p->conn);
		p->conn = NULL;
		goto error;
	}

1343
	return 0;
E
Eric Van Hensbergen 已提交
1344 1345

error:
1346 1347
	kfree(p);
	return err;
E
Eric Van Hensbergen 已提交
1348 1349 1350 1351 1352 1353
}

static struct p9_trans_module p9_tcp_trans = {
	.name = "tcp",
	.maxsize = MAX_SOCK_BUF,
	.def = 1,
1354 1355 1356
	.create = p9_fd_create_tcp,
	.close = p9_fd_close,
	.rpc = p9_fd_rpc,
1357
	.owner = THIS_MODULE,
E
Eric Van Hensbergen 已提交
1358 1359 1360 1361 1362 1363
};

static struct p9_trans_module p9_unix_trans = {
	.name = "unix",
	.maxsize = MAX_SOCK_BUF,
	.def = 0,
1364 1365 1366
	.create = p9_fd_create_unix,
	.close = p9_fd_close,
	.rpc = p9_fd_rpc,
1367
	.owner = THIS_MODULE,
E
Eric Van Hensbergen 已提交
1368 1369 1370 1371 1372 1373
};

static struct p9_trans_module p9_fd_trans = {
	.name = "fd",
	.maxsize = MAX_SOCK_BUF,
	.def = 0,
1374 1375 1376
	.create = p9_fd_create,
	.close = p9_fd_close,
	.rpc = p9_fd_rpc,
1377
	.owner = THIS_MODULE,
E
Eric Van Hensbergen 已提交
1378 1379
};

1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422
/**
 * p9_poll_proc - poll worker thread
 * @a: thread state and arguments
 *
 * polls all v9fs transports for new events and queues the appropriate
 * work to the work queue
 *
 */

static int p9_poll_proc(void *a)
{
	unsigned long flags;

	P9_DPRINTK(P9_DEBUG_MUX, "start %p\n", current);
 repeat:
	spin_lock_irqsave(&p9_poll_lock, flags);
	while (!list_empty(&p9_poll_pending_list)) {
		struct p9_conn *conn = list_first_entry(&p9_poll_pending_list,
							struct p9_conn,
							poll_pending_link);
		list_del_init(&conn->poll_pending_link);
		spin_unlock_irqrestore(&p9_poll_lock, flags);

		p9_poll_mux(conn);

		spin_lock_irqsave(&p9_poll_lock, flags);
	}
	spin_unlock_irqrestore(&p9_poll_lock, flags);

	set_current_state(TASK_INTERRUPTIBLE);
	if (list_empty(&p9_poll_pending_list)) {
		P9_DPRINTK(P9_DEBUG_MUX, "sleeping...\n");
		schedule();
	}
	__set_current_state(TASK_RUNNING);

	if (!kthread_should_stop())
		goto repeat;

	P9_DPRINTK(P9_DEBUG_MUX, "finish\n");
	return 0;
}

1423
int p9_trans_fd_init(void)
E
Eric Van Hensbergen 已提交
1424
{
1425 1426 1427 1428
	p9_mux_wq = create_workqueue("v9fs");
	if (!p9_mux_wq) {
		printk(KERN_WARNING "v9fs: mux: creating workqueue failed\n");
		return -ENOMEM;
1429 1430
	}

T
Tejun Heo 已提交
1431 1432 1433 1434 1435 1436 1437
	p9_poll_task = kthread_run(p9_poll_proc, NULL, "v9fs-poll");
	if (IS_ERR(p9_poll_task)) {
		destroy_workqueue(p9_mux_wq);
		printk(KERN_WARNING "v9fs: mux: creating poll task failed\n");
		return PTR_ERR(p9_poll_task);
	}

E
Eric Van Hensbergen 已提交
1438 1439 1440 1441
	v9fs_register_trans(&p9_tcp_trans);
	v9fs_register_trans(&p9_unix_trans);
	v9fs_register_trans(&p9_fd_trans);

1442
	return 0;
E
Eric Van Hensbergen 已提交
1443
}
1444 1445 1446

void p9_trans_fd_exit(void)
{
T
Tejun Heo 已提交
1447
	kthread_stop(p9_poll_task);
1448 1449 1450
	v9fs_unregister_trans(&p9_tcp_trans);
	v9fs_unregister_trans(&p9_unix_trans);
	v9fs_unregister_trans(&p9_fd_trans);
1451 1452

	destroy_workqueue(p9_mux_wq);
1453
}