aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Van Hensbergen <ericvh@ericvh-desktop.austin.ibm.com>2008-10-13 19:45:24 -0400
committerEric Van Hensbergen <ericvh@gmail.com>2008-10-17 12:04:41 -0400
commit5503ac565998837350f3ee1cc344c36143ea2386 (patch)
tree27144bbbc281b890b76ab75e322b3e0432442e21
parentbead27f0a87f4055f6a0fd69ded9eacced485618 (diff)
9p: remove unnecessary prototypes
Cleanup files by reordering functions in order to remove need for unnecessary function prototypes. There are no code changes here, just functions being moved around and prototypes being eliminated. Signed-off-by: Eric Van Hensbergen <ericvh@gmail.com>
-rw-r--r--net/9p/client.c183
-rw-r--r--net/9p/trans_fd.c860
2 files changed, 495 insertions, 548 deletions
diff --git a/net/9p/client.c b/net/9p/client.c
index f1a52a7ed724..712d4f336adc 100644
--- a/net/9p/client.c
+++ b/net/9p/client.c
@@ -36,10 +36,6 @@
36#include <net/9p/client.h> 36#include <net/9p/client.h>
37#include <net/9p/transport.h> 37#include <net/9p/transport.h>
38 38
39static struct p9_fid *p9_fid_create(struct p9_client *clnt);
40static void p9_fid_destroy(struct p9_fid *fid);
41static struct p9_stat *p9_clone_stat(struct p9_stat *st, int dotu);
42
43/* 39/*
44 * Client Option Parsing (code inspired by NFS code) 40 * Client Option Parsing (code inspired by NFS code)
45 * - a little lazy - parse all client options 41 * - a little lazy - parse all client options
@@ -124,6 +120,55 @@ static int parse_opts(char *opts, struct p9_client *clnt)
124 return ret; 120 return ret;
125} 121}
126 122
123static struct p9_fid *p9_fid_create(struct p9_client *clnt)
124{
125 int err;
126 struct p9_fid *fid;
127
128 P9_DPRINTK(P9_DEBUG_9P, "clnt %p\n", clnt);
129 fid = kmalloc(sizeof(struct p9_fid), GFP_KERNEL);
130 if (!fid)
131 return ERR_PTR(-ENOMEM);
132
133 fid->fid = p9_idpool_get(clnt->fidpool);
134 if (fid->fid < 0) {
135 err = -ENOSPC;
136 goto error;
137 }
138
139 memset(&fid->qid, 0, sizeof(struct p9_qid));
140 fid->mode = -1;
141 fid->rdir_fpos = 0;
142 fid->rdir_pos = 0;
143 fid->rdir_fcall = NULL;
144 fid->uid = current->fsuid;
145 fid->clnt = clnt;
146 fid->aux = NULL;
147
148 spin_lock(&clnt->lock);
149 list_add(&fid->flist, &clnt->fidlist);
150 spin_unlock(&clnt->lock);
151
152 return fid;
153
154error:
155 kfree(fid);
156 return ERR_PTR(err);
157}
158
159static void p9_fid_destroy(struct p9_fid *fid)
160{
161 struct p9_client *clnt;
162
163 P9_DPRINTK(P9_DEBUG_9P, "fid %d\n", fid->fid);
164 clnt = fid->clnt;
165 p9_idpool_put(fid->fid, clnt->fidpool);
166 spin_lock(&clnt->lock);
167 list_del(&fid->flist);
168 spin_unlock(&clnt->lock);
169 kfree(fid->rdir_fcall);
170 kfree(fid);
171}
127 172
128/** 173/**
129 * p9_client_rpc - sends 9P request and waits until a response is available. 174 * p9_client_rpc - sends 9P request and waits until a response is available.
@@ -815,6 +860,46 @@ int p9_client_readn(struct p9_fid *fid, char *data, u64 offset, u32 count)
815} 860}
816EXPORT_SYMBOL(p9_client_readn); 861EXPORT_SYMBOL(p9_client_readn);
817 862
863static struct p9_stat *p9_clone_stat(struct p9_stat *st, int dotu)
864{
865 int n;
866 char *p;
867 struct p9_stat *ret;
868
869 n = sizeof(struct p9_stat) + st->name.len + st->uid.len + st->gid.len +
870 st->muid.len;
871
872 if (dotu)
873 n += st->extension.len;
874
875 ret = kmalloc(n, GFP_KERNEL);
876 if (!ret)
877 return ERR_PTR(-ENOMEM);
878
879 memmove(ret, st, sizeof(struct p9_stat));
880 p = ((char *) ret) + sizeof(struct p9_stat);
881 memmove(p, st->name.str, st->name.len);
882 ret->name.str = p;
883 p += st->name.len;
884 memmove(p, st->uid.str, st->uid.len);
885 ret->uid.str = p;
886 p += st->uid.len;
887 memmove(p, st->gid.str, st->gid.len);
888 ret->gid.str = p;
889 p += st->gid.len;
890 memmove(p, st->muid.str, st->muid.len);
891 ret->muid.str = p;
892 p += st->muid.len;
893
894 if (dotu) {
895 memmove(p, st->extension.str, st->extension.len);
896 ret->extension.str = p;
897 p += st->extension.len;
898 }
899
900 return ret;
901}
902
818struct p9_stat *p9_client_stat(struct p9_fid *fid) 903struct p9_stat *p9_client_stat(struct p9_fid *fid)
819{ 904{
820 int err; 905 int err;
@@ -986,93 +1071,3 @@ error:
986 return ERR_PTR(err); 1071 return ERR_PTR(err);
987} 1072}
988EXPORT_SYMBOL(p9_client_dirread); 1073EXPORT_SYMBOL(p9_client_dirread);
989
990static struct p9_stat *p9_clone_stat(struct p9_stat *st, int dotu)
991{
992 int n;
993 char *p;
994 struct p9_stat *ret;
995
996 n = sizeof(struct p9_stat) + st->name.len + st->uid.len + st->gid.len +
997 st->muid.len;
998
999 if (dotu)
1000 n += st->extension.len;
1001
1002 ret = kmalloc(n, GFP_KERNEL);
1003 if (!ret)
1004 return ERR_PTR(-ENOMEM);
1005
1006 memmove(ret, st, sizeof(struct p9_stat));
1007 p = ((char *) ret) + sizeof(struct p9_stat);
1008 memmove(p, st->name.str, st->name.len);
1009 ret->name.str = p;
1010 p += st->name.len;
1011 memmove(p, st->uid.str, st->uid.len);
1012 ret->uid.str = p;
1013 p += st->uid.len;
1014 memmove(p, st->gid.str, st->gid.len);
1015 ret->gid.str = p;
1016 p += st->gid.len;
1017 memmove(p, st->muid.str, st->muid.len);
1018 ret->muid.str = p;
1019 p += st->muid.len;
1020
1021 if (dotu) {
1022 memmove(p, st->extension.str, st->extension.len);
1023 ret->extension.str = p;
1024 p += st->extension.len;
1025 }
1026
1027 return ret;
1028}
1029
1030static struct p9_fid *p9_fid_create(struct p9_client *clnt)
1031{
1032 int err;
1033 struct p9_fid *fid;
1034
1035 P9_DPRINTK(P9_DEBUG_9P, "clnt %p\n", clnt);
1036 fid = kmalloc(sizeof(struct p9_fid), GFP_KERNEL);
1037 if (!fid)
1038 return ERR_PTR(-ENOMEM);
1039
1040 fid->fid = p9_idpool_get(clnt->fidpool);
1041 if (fid->fid < 0) {
1042 err = -ENOSPC;
1043 goto error;
1044 }
1045
1046 memset(&fid->qid, 0, sizeof(struct p9_qid));
1047 fid->mode = -1;
1048 fid->rdir_fpos = 0;
1049 fid->rdir_pos = 0;
1050 fid->rdir_fcall = NULL;
1051 fid->uid = current->fsuid;
1052 fid->clnt = clnt;
1053 fid->aux = NULL;
1054
1055 spin_lock(&clnt->lock);
1056 list_add(&fid->flist, &clnt->fidlist);
1057 spin_unlock(&clnt->lock);
1058
1059 return fid;
1060
1061error:
1062 kfree(fid);
1063 return ERR_PTR(err);
1064}
1065
1066static void p9_fid_destroy(struct p9_fid *fid)
1067{
1068 struct p9_client *clnt;
1069
1070 P9_DPRINTK(P9_DEBUG_9P, "fid %d\n", fid->fid);
1071 clnt = fid->clnt;
1072 p9_idpool_put(fid->fid, clnt->fidpool);
1073 spin_lock(&clnt->lock);
1074 list_del(&fid->flist);
1075 spin_unlock(&clnt->lock);
1076 kfree(fid->rdir_fcall);
1077 kfree(fid);
1078}
diff --git a/net/9p/trans_fd.c b/net/9p/trans_fd.c
index bc5b6965981b..334d39cc5ba3 100644
--- a/net/9p/trans_fd.c
+++ b/net/9p/trans_fd.c
@@ -61,7 +61,6 @@ struct p9_fd_opts {
61 u16 port; 61 u16 port;
62}; 62};
63 63
64
65/** 64/**
66 * struct p9_trans_fd - transport state 65 * struct p9_trans_fd - transport state
67 * @rd: reference to file to read from 66 * @rd: reference to file to read from
@@ -206,30 +205,11 @@ struct p9_mux_rpc {
206 wait_queue_head_t wqueue; 205 wait_queue_head_t wqueue;
207}; 206};
208 207
209static int p9_poll_proc(void *);
210static void p9_read_work(struct work_struct *work);
211static void p9_write_work(struct work_struct *work);
212static void p9_pollwait(struct file *filp, wait_queue_head_t *wait_address,
213 poll_table *p);
214static int p9_fd_write(struct p9_client *client, void *v, int len);
215static int p9_fd_read(struct p9_client *client, void *v, int len);
216
217static DEFINE_SPINLOCK(p9_poll_lock); 208static DEFINE_SPINLOCK(p9_poll_lock);
218static LIST_HEAD(p9_poll_pending_list); 209static LIST_HEAD(p9_poll_pending_list);
219static struct workqueue_struct *p9_mux_wq; 210static struct workqueue_struct *p9_mux_wq;
220static struct task_struct *p9_poll_task; 211static struct task_struct *p9_poll_task;
221 212
222static void p9_conn_destroy(struct p9_conn *);
223static unsigned int p9_fd_poll(struct p9_client *client,
224 struct poll_table_struct *pt);
225
226#ifdef P9_NONBLOCK
227static int p9_conn_rpcnb(struct p9_conn *m, struct p9_fcall *tc,
228 p9_conn_req_callback cb, void *a);
229#endif /* P9_NONBLOCK */
230
231static void p9_conn_cancel(struct p9_conn *m, int err);
232
233static u16 p9_mux_get_tag(struct p9_conn *m) 213static u16 p9_mux_get_tag(struct p9_conn *m)
234{ 214{
235 int tag; 215 int tag;
@@ -267,303 +247,38 @@ static void p9_mux_poll_stop(struct p9_conn *m)
267} 247}
268 248
269/** 249/**
270 * p9_conn_create - allocate and initialize the per-session mux data 250 * p9_conn_cancel - cancel all pending requests with error
271 * @client: client instance 251 * @m: mux data
272 * 252 * @err: error code
273 * Note: Creates the polling task if this is the first session.
274 */
275
276static struct p9_conn *p9_conn_create(struct p9_client *client)
277{
278 int i, n;
279 struct p9_conn *m;
280
281 P9_DPRINTK(P9_DEBUG_MUX, "client %p msize %d\n", client, client->msize);
282 m = kzalloc(sizeof(struct p9_conn), GFP_KERNEL);
283 if (!m)
284 return ERR_PTR(-ENOMEM);
285
286 spin_lock_init(&m->lock);
287 INIT_LIST_HEAD(&m->mux_list);
288 m->client = client;
289 m->tagpool = p9_idpool_create();
290 if (IS_ERR(m->tagpool)) {
291 kfree(m);
292 return ERR_PTR(-ENOMEM);
293 }
294
295 INIT_LIST_HEAD(&m->req_list);
296 INIT_LIST_HEAD(&m->unsent_req_list);
297 INIT_WORK(&m->rq, p9_read_work);
298 INIT_WORK(&m->wq, p9_write_work);
299 INIT_LIST_HEAD(&m->poll_pending_link);
300 init_poll_funcptr(&m->pt, p9_pollwait);
301
302 n = p9_fd_poll(client, &m->pt);
303 if (n & POLLIN) {
304 P9_DPRINTK(P9_DEBUG_MUX, "mux %p can read\n", m);
305 set_bit(Rpending, &m->wsched);
306 }
307
308 if (n & POLLOUT) {
309 P9_DPRINTK(P9_DEBUG_MUX, "mux %p can write\n", m);
310 set_bit(Wpending, &m->wsched);
311 }
312
313 for (i = 0; i < ARRAY_SIZE(m->poll_wait); i++) {
314 if (IS_ERR(m->poll_wait[i].wait_addr)) {
315 p9_mux_poll_stop(m);
316 kfree(m);
317 /* return the error code */
318 return (void *)m->poll_wait[i].wait_addr;
319 }
320 }
321
322 return m;
323}
324
325/**
326 * p9_mux_destroy - cancels all pending requests and frees mux resources
327 * @m: mux to destroy
328 *
329 */
330
331static void p9_conn_destroy(struct p9_conn *m)
332{
333 P9_DPRINTK(P9_DEBUG_MUX, "mux %p prev %p next %p\n", m,
334 m->mux_list.prev, m->mux_list.next);
335
336 p9_mux_poll_stop(m);
337 cancel_work_sync(&m->rq);
338 cancel_work_sync(&m->wq);
339
340 p9_conn_cancel(m, -ECONNRESET);
341
342 m->client = NULL;
343 p9_idpool_destroy(m->tagpool);
344 kfree(m);
345}
346
347static int p9_pollwake(wait_queue_t *wait, unsigned mode, int sync, void *key)
348{
349 struct p9_poll_wait *pwait =
350 container_of(wait, struct p9_poll_wait, wait);
351 struct p9_conn *m = pwait->conn;
352 unsigned long flags;
353 DECLARE_WAITQUEUE(dummy_wait, p9_poll_task);
354
355 spin_lock_irqsave(&p9_poll_lock, flags);
356 if (list_empty(&m->poll_pending_link))
357 list_add_tail(&m->poll_pending_link, &p9_poll_pending_list);
358 spin_unlock_irqrestore(&p9_poll_lock, flags);
359
360 /* perform the default wake up operation */
361 return default_wake_function(&dummy_wait, mode, sync, key);
362}
363
364/**
365 * p9_pollwait - add poll task to the wait queue
366 * @filp: file pointer being polled
367 * @wait_address: wait_q to block on
368 * @p: poll state
369 *
370 * called by files poll operation to add v9fs-poll task to files wait queue
371 */
372
373static void
374p9_pollwait(struct file *filp, wait_queue_head_t *wait_address, poll_table *p)
375{
376 struct p9_conn *m = container_of(p, struct p9_conn, pt);
377 struct p9_poll_wait *pwait = NULL;
378 int i;
379
380 for (i = 0; i < ARRAY_SIZE(m->poll_wait); i++) {
381 if (m->poll_wait[i].wait_addr == NULL) {
382 pwait = &m->poll_wait[i];
383 break;
384 }
385 }
386
387 if (!pwait) {
388 P9_DPRINTK(P9_DEBUG_ERROR, "not enough wait_address slots\n");
389 return;
390 }
391
392 if (!wait_address) {
393 P9_DPRINTK(P9_DEBUG_ERROR, "no wait_address\n");
394 pwait->wait_addr = ERR_PTR(-EIO);
395 return;
396 }
397
398 pwait->conn = m;
399 pwait->wait_addr = wait_address;
400 init_waitqueue_func_entry(&pwait->wait, p9_pollwake);
401 add_wait_queue(wait_address, &pwait->wait);
402}
403
404/**
405 * p9_poll_mux - polls a mux and schedules read or write works if necessary
406 * @m: connection to poll
407 *
408 */
409
410static void p9_poll_mux(struct p9_conn *m)
411{
412 int n;
413
414 if (m->err < 0)
415 return;
416
417 n = p9_fd_poll(m->client, NULL);
418 if (n < 0 || n & (POLLERR | POLLHUP | POLLNVAL)) {
419 P9_DPRINTK(P9_DEBUG_MUX, "error mux %p err %d\n", m, n);
420 if (n >= 0)
421 n = -ECONNRESET;
422 p9_conn_cancel(m, n);
423 }
424
425 if (n & POLLIN) {
426 set_bit(Rpending, &m->wsched);
427 P9_DPRINTK(P9_DEBUG_MUX, "mux %p can read\n", m);
428 if (!test_and_set_bit(Rworksched, &m->wsched)) {
429 P9_DPRINTK(P9_DEBUG_MUX, "schedule read work %p\n", m);
430 queue_work(p9_mux_wq, &m->rq);
431 }
432 }
433
434 if (n & POLLOUT) {
435 set_bit(Wpending, &m->wsched);
436 P9_DPRINTK(P9_DEBUG_MUX, "mux %p can write\n", m);
437 if ((m->wsize || !list_empty(&m->unsent_req_list))
438 && !test_and_set_bit(Wworksched, &m->wsched)) {
439 P9_DPRINTK(P9_DEBUG_MUX, "schedule write work %p\n", m);
440 queue_work(p9_mux_wq, &m->wq);
441 }
442 }
443}
444
445/**
446 * p9_poll_proc - poll worker thread
447 * @a: thread state and arguments
448 *
449 * polls all v9fs transports for new events and queues the appropriate
450 * work to the work queue
451 *
452 */
453
454static int p9_poll_proc(void *a)
455{
456 unsigned long flags;
457
458 P9_DPRINTK(P9_DEBUG_MUX, "start %p\n", current);
459 repeat:
460 spin_lock_irqsave(&p9_poll_lock, flags);
461 while (!list_empty(&p9_poll_pending_list)) {
462 struct p9_conn *conn = list_first_entry(&p9_poll_pending_list,
463 struct p9_conn,
464 poll_pending_link);
465 list_del_init(&conn->poll_pending_link);
466 spin_unlock_irqrestore(&p9_poll_lock, flags);
467
468 p9_poll_mux(conn);
469
470 spin_lock_irqsave(&p9_poll_lock, flags);
471 }
472 spin_unlock_irqrestore(&p9_poll_lock, flags);
473
474 set_current_state(TASK_INTERRUPTIBLE);
475 if (list_empty(&p9_poll_pending_list)) {
476 P9_DPRINTK(P9_DEBUG_MUX, "sleeping...\n");
477 schedule();
478 }
479 __set_current_state(TASK_RUNNING);
480
481 if (!kthread_should_stop())
482 goto repeat;
483
484 P9_DPRINTK(P9_DEBUG_MUX, "finish\n");
485 return 0;
486}
487
488/**
489 * p9_write_work - called when a transport can send some data
490 * @work: container for work to be done
491 * 253 *
492 */ 254 */
493 255
494static void p9_write_work(struct work_struct *work) 256void p9_conn_cancel(struct p9_conn *m, int err)
495{ 257{
496 int n, err; 258 struct p9_req *req, *rtmp;
497 struct p9_conn *m; 259 LIST_HEAD(cancel_list);
498 struct p9_req *req;
499
500 m = container_of(work, struct p9_conn, wq);
501
502 if (m->err < 0) {
503 clear_bit(Wworksched, &m->wsched);
504 return;
505 }
506
507 if (!m->wsize) {
508 if (list_empty(&m->unsent_req_list)) {
509 clear_bit(Wworksched, &m->wsched);
510 return;
511 }
512
513 spin_lock(&m->lock);
514again:
515 req = list_entry(m->unsent_req_list.next, struct p9_req,
516 req_list);
517 list_move_tail(&req->req_list, &m->req_list);
518 if (req->err == ERREQFLUSH)
519 goto again;
520
521 m->wbuf = req->tcall->sdata;
522 m->wsize = req->tcall->size;
523 m->wpos = 0;
524 spin_unlock(&m->lock);
525 }
526 260
527 P9_DPRINTK(P9_DEBUG_MUX, "mux %p pos %d size %d\n", m, m->wpos, 261 P9_DPRINTK(P9_DEBUG_ERROR, "mux %p err %d\n", m, err);
528 m->wsize); 262 m->err = err;
529 clear_bit(Wpending, &m->wsched); 263 spin_lock(&m->lock);
530 err = p9_fd_write(m->client, m->wbuf + m->wpos, m->wsize - m->wpos); 264 list_for_each_entry_safe(req, rtmp, &m->req_list, req_list) {
531 P9_DPRINTK(P9_DEBUG_MUX, "mux %p sent %d bytes\n", m, err); 265 list_move(&req->req_list, &cancel_list);
532 if (err == -EAGAIN) {
533 clear_bit(Wworksched, &m->wsched);
534 return;
535 } 266 }
536 267 list_for_each_entry_safe(req, rtmp, &m->unsent_req_list, req_list) {
537 if (err < 0) 268 list_move(&req->req_list, &cancel_list);
538 goto error;
539 else if (err == 0) {
540 err = -EREMOTEIO;
541 goto error;
542 } 269 }
270 spin_unlock(&m->lock);
543 271
544 m->wpos += err; 272 list_for_each_entry_safe(req, rtmp, &cancel_list, req_list) {
545 if (m->wpos == m->wsize) 273 list_del(&req->req_list);
546 m->wpos = m->wsize = 0; 274 if (!req->err)
275 req->err = err;
547 276
548 if (m->wsize == 0 && !list_empty(&m->unsent_req_list)) { 277 if (req->cb)
549 if (test_and_clear_bit(Wpending, &m->wsched)) 278 (*req->cb) (req, req->cba);
550 n = POLLOUT;
551 else 279 else
552 n = p9_fd_poll(m->client, NULL); 280 kfree(req->rcall);
553 281 }
554 if (n & POLLOUT) {
555 P9_DPRINTK(P9_DEBUG_MUX, "schedule write work %p\n", m);
556 queue_work(p9_mux_wq, &m->wq);
557 } else
558 clear_bit(Wworksched, &m->wsched);
559 } else
560 clear_bit(Wworksched, &m->wsched);
561
562 return;
563
564error:
565 p9_conn_cancel(m, err);
566 clear_bit(Wworksched, &m->wsched);
567} 282}
568 283
569static void process_request(struct p9_conn *m, struct p9_req *req) 284static void process_request(struct p9_conn *m, struct p9_req *req)
@@ -599,6 +314,66 @@ static void process_request(struct p9_conn *m, struct p9_req *req)
599 } 314 }
600} 315}
601 316
317static unsigned int
318p9_fd_poll(struct p9_client *client, struct poll_table_struct *pt)
319{
320 int ret, n;
321 struct p9_trans_fd *ts = NULL;
322
323 if (client && client->status == Connected)
324 ts = client->trans;
325
326 if (!ts)
327 return -EREMOTEIO;
328
329 if (!ts->rd->f_op || !ts->rd->f_op->poll)
330 return -EIO;
331
332 if (!ts->wr->f_op || !ts->wr->f_op->poll)
333 return -EIO;
334
335 ret = ts->rd->f_op->poll(ts->rd, pt);
336 if (ret < 0)
337 return ret;
338
339 if (ts->rd != ts->wr) {
340 n = ts->wr->f_op->poll(ts->wr, pt);
341 if (n < 0)
342 return n;
343 ret = (ret & ~POLLOUT) | (n & ~POLLIN);
344 }
345
346 return ret;
347}
348
349/**
350 * p9_fd_read- read from a fd
351 * @client: client instance
352 * @v: buffer to receive data into
353 * @len: size of receive buffer
354 *
355 */
356
357static int p9_fd_read(struct p9_client *client, void *v, int len)
358{
359 int ret;
360 struct p9_trans_fd *ts = NULL;
361
362 if (client && client->status != Disconnected)
363 ts = client->trans;
364
365 if (!ts)
366 return -EREMOTEIO;
367
368 if (!(ts->rd->f_flags & O_NONBLOCK))
369 P9_DPRINTK(P9_DEBUG_ERROR, "blocking read ...\n");
370
371 ret = kernel_read(ts->rd, ts->rd->f_pos, v, len);
372 if (ret <= 0 && ret != -ERESTARTSYS && ret != -EAGAIN)
373 client->status = Disconnected;
374 return ret;
375}
376
602/** 377/**
603 * p9_read_work - called when there is some data to be read from a transport 378 * p9_read_work - called when there is some data to be read from a transport
604 * @work: container of work to be done 379 * @work: container of work to be done
@@ -749,6 +524,275 @@ error:
749} 524}
750 525
751/** 526/**
527 * p9_fd_write - write to a socket
528 * @client: client instance
529 * @v: buffer to send data from
530 * @len: size of send buffer
531 *
532 */
533
534static int p9_fd_write(struct p9_client *client, void *v, int len)
535{
536 int ret;
537 mm_segment_t oldfs;
538 struct p9_trans_fd *ts = NULL;
539
540 if (client && client->status != Disconnected)
541 ts = client->trans;
542
543 if (!ts)
544 return -EREMOTEIO;
545
546 if (!(ts->wr->f_flags & O_NONBLOCK))
547 P9_DPRINTK(P9_DEBUG_ERROR, "blocking write ...\n");
548
549 oldfs = get_fs();
550 set_fs(get_ds());
551 /* The cast to a user pointer is valid due to the set_fs() */
552 ret = vfs_write(ts->wr, (void __user *)v, len, &ts->wr->f_pos);
553 set_fs(oldfs);
554
555 if (ret <= 0 && ret != -ERESTARTSYS && ret != -EAGAIN)
556 client->status = Disconnected;
557 return ret;
558}
559
560/**
561 * p9_write_work - called when a transport can send some data
562 * @work: container for work to be done
563 *
564 */
565
566static void p9_write_work(struct work_struct *work)
567{
568 int n, err;
569 struct p9_conn *m;
570 struct p9_req *req;
571
572 m = container_of(work, struct p9_conn, wq);
573
574 if (m->err < 0) {
575 clear_bit(Wworksched, &m->wsched);
576 return;
577 }
578
579 if (!m->wsize) {
580 if (list_empty(&m->unsent_req_list)) {
581 clear_bit(Wworksched, &m->wsched);
582 return;
583 }
584
585 spin_lock(&m->lock);
586again:
587 req = list_entry(m->unsent_req_list.next, struct p9_req,
588 req_list);
589 list_move_tail(&req->req_list, &m->req_list);
590 if (req->err == ERREQFLUSH)
591 goto again;
592
593 m->wbuf = req->tcall->sdata;
594 m->wsize = req->tcall->size;
595 m->wpos = 0;
596 spin_unlock(&m->lock);
597 }
598
599 P9_DPRINTK(P9_DEBUG_MUX, "mux %p pos %d size %d\n", m, m->wpos,
600 m->wsize);
601 clear_bit(Wpending, &m->wsched);
602 err = p9_fd_write(m->client, m->wbuf + m->wpos, m->wsize - m->wpos);
603 P9_DPRINTK(P9_DEBUG_MUX, "mux %p sent %d bytes\n", m, err);
604 if (err == -EAGAIN) {
605 clear_bit(Wworksched, &m->wsched);
606 return;
607 }
608
609 if (err < 0)
610 goto error;
611 else if (err == 0) {
612 err = -EREMOTEIO;
613 goto error;
614 }
615
616 m->wpos += err;
617 if (m->wpos == m->wsize)
618 m->wpos = m->wsize = 0;
619
620 if (m->wsize == 0 && !list_empty(&m->unsent_req_list)) {
621 if (test_and_clear_bit(Wpending, &m->wsched))
622 n = POLLOUT;
623 else
624 n = p9_fd_poll(m->client, NULL);
625
626 if (n & POLLOUT) {
627 P9_DPRINTK(P9_DEBUG_MUX, "schedule write work %p\n", m);
628 queue_work(p9_mux_wq, &m->wq);
629 } else
630 clear_bit(Wworksched, &m->wsched);
631 } else
632 clear_bit(Wworksched, &m->wsched);
633
634 return;
635
636error:
637 p9_conn_cancel(m, err);
638 clear_bit(Wworksched, &m->wsched);
639}
640
641static int p9_pollwake(wait_queue_t *wait, unsigned mode, int sync, void *key)
642{
643 struct p9_poll_wait *pwait =
644 container_of(wait, struct p9_poll_wait, wait);
645 struct p9_conn *m = pwait->conn;
646 unsigned long flags;
647 DECLARE_WAITQUEUE(dummy_wait, p9_poll_task);
648
649 spin_lock_irqsave(&p9_poll_lock, flags);
650 if (list_empty(&m->poll_pending_link))
651 list_add_tail(&m->poll_pending_link, &p9_poll_pending_list);
652 spin_unlock_irqrestore(&p9_poll_lock, flags);
653
654 /* perform the default wake up operation */
655 return default_wake_function(&dummy_wait, mode, sync, key);
656}
657
658/**
659 * p9_pollwait - add poll task to the wait queue
660 * @filp: file pointer being polled
661 * @wait_address: wait_q to block on
662 * @p: poll state
663 *
664 * called by files poll operation to add v9fs-poll task to files wait queue
665 */
666
667static void
668p9_pollwait(struct file *filp, wait_queue_head_t *wait_address, poll_table *p)
669{
670 struct p9_conn *m = container_of(p, struct p9_conn, pt);
671 struct p9_poll_wait *pwait = NULL;
672 int i;
673
674 for (i = 0; i < ARRAY_SIZE(m->poll_wait); i++) {
675 if (m->poll_wait[i].wait_addr == NULL) {
676 pwait = &m->poll_wait[i];
677 break;
678 }
679 }
680
681 if (!pwait) {
682 P9_DPRINTK(P9_DEBUG_ERROR, "not enough wait_address slots\n");
683 return;
684 }
685
686 if (!wait_address) {
687 P9_DPRINTK(P9_DEBUG_ERROR, "no wait_address\n");
688 pwait->wait_addr = ERR_PTR(-EIO);
689 return;
690 }
691
692 pwait->conn = m;
693 pwait->wait_addr = wait_address;
694 init_waitqueue_func_entry(&pwait->wait, p9_pollwake);
695 add_wait_queue(wait_address, &pwait->wait);
696}
697
698/**
699 * p9_conn_create - allocate and initialize the per-session mux data
700 * @client: client instance
701 *
702 * Note: Creates the polling task if this is the first session.
703 */
704
705static struct p9_conn *p9_conn_create(struct p9_client *client)
706{
707 int i, n;
708 struct p9_conn *m;
709
710 P9_DPRINTK(P9_DEBUG_MUX, "client %p msize %d\n", client, client->msize);
711 m = kzalloc(sizeof(struct p9_conn), GFP_KERNEL);
712 if (!m)
713 return ERR_PTR(-ENOMEM);
714
715 spin_lock_init(&m->lock);
716 INIT_LIST_HEAD(&m->mux_list);
717 m->client = client;
718 m->tagpool = p9_idpool_create();
719 if (IS_ERR(m->tagpool)) {
720 kfree(m);
721 return ERR_PTR(-ENOMEM);
722 }
723
724 INIT_LIST_HEAD(&m->req_list);
725 INIT_LIST_HEAD(&m->unsent_req_list);
726 INIT_WORK(&m->rq, p9_read_work);
727 INIT_WORK(&m->wq, p9_write_work);
728 INIT_LIST_HEAD(&m->poll_pending_link);
729 init_poll_funcptr(&m->pt, p9_pollwait);
730
731 n = p9_fd_poll(client, &m->pt);
732 if (n & POLLIN) {
733 P9_DPRINTK(P9_DEBUG_MUX, "mux %p can read\n", m);
734 set_bit(Rpending, &m->wsched);
735 }
736
737 if (n & POLLOUT) {
738 P9_DPRINTK(P9_DEBUG_MUX, "mux %p can write\n", m);
739 set_bit(Wpending, &m->wsched);
740 }
741
742 for (i = 0; i < ARRAY_SIZE(m->poll_wait); i++) {
743 if (IS_ERR(m->poll_wait[i].wait_addr)) {
744 p9_mux_poll_stop(m);
745 kfree(m);
746 /* return the error code */
747 return (void *)m->poll_wait[i].wait_addr;
748 }
749 }
750
751 return m;
752}
753
754/**
755 * p9_poll_mux - polls a mux and schedules read or write works if necessary
756 * @m: connection to poll
757 *
758 */
759
760static void p9_poll_mux(struct p9_conn *m)
761{
762 int n;
763
764 if (m->err < 0)
765 return;
766
767 n = p9_fd_poll(m->client, NULL);
768 if (n < 0 || n & (POLLERR | POLLHUP | POLLNVAL)) {
769 P9_DPRINTK(P9_DEBUG_MUX, "error mux %p err %d\n", m, n);
770 if (n >= 0)
771 n = -ECONNRESET;
772 p9_conn_cancel(m, n);
773 }
774
775 if (n & POLLIN) {
776 set_bit(Rpending, &m->wsched);
777 P9_DPRINTK(P9_DEBUG_MUX, "mux %p can read\n", m);
778 if (!test_and_set_bit(Rworksched, &m->wsched)) {
779 P9_DPRINTK(P9_DEBUG_MUX, "schedule read work %p\n", m);
780 queue_work(p9_mux_wq, &m->rq);
781 }
782 }
783
784 if (n & POLLOUT) {
785 set_bit(Wpending, &m->wsched);
786 P9_DPRINTK(P9_DEBUG_MUX, "mux %p can write\n", m);
787 if ((m->wsize || !list_empty(&m->unsent_req_list))
788 && !test_and_set_bit(Wworksched, &m->wsched)) {
789 P9_DPRINTK(P9_DEBUG_MUX, "schedule write work %p\n", m);
790 queue_work(p9_mux_wq, &m->wq);
791 }
792 }
793}
794
795/**
752 * p9_send_request - send 9P request 796 * p9_send_request - send 9P request
753 * The function can sleep until the request is scheduled for sending. 797 * The function can sleep until the request is scheduled for sending.
754 * The function can be interrupted. Return from the function is not 798 * The function can be interrupted. Return from the function is not
@@ -1005,69 +1049,6 @@ p9_fd_rpc(struct p9_client *client, struct p9_fcall *tc, struct p9_fcall **rc)
1005 return err; 1049 return err;
1006} 1050}
1007 1051
1008#ifdef P9_NONBLOCK
1009/**
1010 * p9_conn_rpcnb - sends 9P request without waiting for response.
1011 * @m: mux data
1012 * @tc: request to be sent
1013 * @cb: callback function to be called when response arrives
1014 * @a: value to pass to the callback function
1015 *
1016 */
1017
1018int p9_conn_rpcnb(struct p9_conn *m, struct p9_fcall *tc,
1019 p9_conn_req_callback cb, void *a)
1020{
1021 int err;
1022 struct p9_req *req;
1023
1024 req = p9_send_request(m, tc, cb, a);
1025 if (IS_ERR(req)) {
1026 err = PTR_ERR(req);
1027 P9_DPRINTK(P9_DEBUG_MUX, "error %d\n", err);
1028 return PTR_ERR(req);
1029 }
1030
1031 P9_DPRINTK(P9_DEBUG_MUX, "mux %p tc %p tag %d\n", m, tc, req->tag);
1032 return 0;
1033}
1034#endif /* P9_NONBLOCK */
1035
1036/**
1037 * p9_conn_cancel - cancel all pending requests with error
1038 * @m: mux data
1039 * @err: error code
1040 *
1041 */
1042
1043void p9_conn_cancel(struct p9_conn *m, int err)
1044{
1045 struct p9_req *req, *rtmp;
1046 LIST_HEAD(cancel_list);
1047
1048 P9_DPRINTK(P9_DEBUG_ERROR, "mux %p err %d\n", m, err);
1049 m->err = err;
1050 spin_lock(&m->lock);
1051 list_for_each_entry_safe(req, rtmp, &m->req_list, req_list) {
1052 list_move(&req->req_list, &cancel_list);
1053 }
1054 list_for_each_entry_safe(req, rtmp, &m->unsent_req_list, req_list) {
1055 list_move(&req->req_list, &cancel_list);
1056 }
1057 spin_unlock(&m->lock);
1058
1059 list_for_each_entry_safe(req, rtmp, &cancel_list, req_list) {
1060 list_del(&req->req_list);
1061 if (!req->err)
1062 req->err = err;
1063
1064 if (req->cb)
1065 (*req->cb) (req, req->cba);
1066 else
1067 kfree(req->rcall);
1068 }
1069}
1070
1071/** 1052/**
1072 * parse_options - parse mount options into session structure 1053 * parse_options - parse mount options into session structure
1073 * @options: options string passed from mount 1054 * @options: options string passed from mount
@@ -1177,97 +1158,25 @@ static int p9_socket_open(struct p9_client *client, struct socket *csocket)
1177} 1158}
1178 1159
1179/** 1160/**
1180 * p9_fd_read- read from a fd 1161 * p9_mux_destroy - cancels all pending requests and frees mux resources
1181 * @client: client instance 1162 * @m: mux to destroy
1182 * @v: buffer to receive data into
1183 * @len: size of receive buffer
1184 *
1185 */
1186
1187static int p9_fd_read(struct p9_client *client, void *v, int len)
1188{
1189 int ret;
1190 struct p9_trans_fd *ts = NULL;
1191
1192 if (client && client->status != Disconnected)
1193 ts = client->trans;
1194
1195 if (!ts)
1196 return -EREMOTEIO;
1197
1198 if (!(ts->rd->f_flags & O_NONBLOCK))
1199 P9_DPRINTK(P9_DEBUG_ERROR, "blocking read ...\n");
1200
1201 ret = kernel_read(ts->rd, ts->rd->f_pos, v, len);
1202 if (ret <= 0 && ret != -ERESTARTSYS && ret != -EAGAIN)
1203 client->status = Disconnected;
1204 return ret;
1205}
1206
1207/**
1208 * p9_fd_write - write to a socket
1209 * @client: client instance
1210 * @v: buffer to send data from
1211 * @len: size of send buffer
1212 * 1163 *
1213 */ 1164 */
1214 1165
1215static int p9_fd_write(struct p9_client *client, void *v, int len) 1166static void p9_conn_destroy(struct p9_conn *m)
1216{
1217 int ret;
1218 mm_segment_t oldfs;
1219 struct p9_trans_fd *ts = NULL;
1220
1221 if (client && client->status != Disconnected)
1222 ts = client->trans;
1223
1224 if (!ts)
1225 return -EREMOTEIO;
1226
1227 if (!(ts->wr->f_flags & O_NONBLOCK))
1228 P9_DPRINTK(P9_DEBUG_ERROR, "blocking write ...\n");
1229
1230 oldfs = get_fs();
1231 set_fs(get_ds());
1232 /* The cast to a user pointer is valid due to the set_fs() */
1233 ret = vfs_write(ts->wr, (void __user *)v, len, &ts->wr->f_pos);
1234 set_fs(oldfs);
1235
1236 if (ret <= 0 && ret != -ERESTARTSYS && ret != -EAGAIN)
1237 client->status = Disconnected;
1238 return ret;
1239}
1240
1241static unsigned int
1242p9_fd_poll(struct p9_client *client, struct poll_table_struct *pt)
1243{ 1167{
1244 int ret, n; 1168 P9_DPRINTK(P9_DEBUG_MUX, "mux %p prev %p next %p\n", m,
1245 struct p9_trans_fd *ts = NULL; 1169 m->mux_list.prev, m->mux_list.next);
1246
1247 if (client && client->status == Connected)
1248 ts = client->trans;
1249
1250 if (!ts)
1251 return -EREMOTEIO;
1252
1253 if (!ts->rd->f_op || !ts->rd->f_op->poll)
1254 return -EIO;
1255
1256 if (!ts->wr->f_op || !ts->wr->f_op->poll)
1257 return -EIO;
1258 1170
1259 ret = ts->rd->f_op->poll(ts->rd, pt); 1171 p9_mux_poll_stop(m);
1260 if (ret < 0) 1172 cancel_work_sync(&m->rq);
1261 return ret; 1173 cancel_work_sync(&m->wq);
1262 1174
1263 if (ts->rd != ts->wr) { 1175 p9_conn_cancel(m, -ECONNRESET);
1264 n = ts->wr->f_op->poll(ts->wr, pt);
1265 if (n < 0)
1266 return n;
1267 ret = (ret & ~POLLOUT) | (n & ~POLLIN);
1268 }
1269 1176
1270 return ret; 1177 m->client = NULL;
1178 p9_idpool_destroy(m->tagpool);
1179 kfree(m);
1271} 1180}
1272 1181
1273/** 1182/**
@@ -1492,6 +1401,49 @@ static struct p9_trans_module p9_fd_trans = {
1492 .owner = THIS_MODULE, 1401 .owner = THIS_MODULE,
1493}; 1402};
1494 1403
1404/**
1405 * p9_poll_proc - poll worker thread
1406 * @a: thread state and arguments
1407 *
1408 * polls all v9fs transports for new events and queues the appropriate
1409 * work to the work queue
1410 *
1411 */
1412
1413static int p9_poll_proc(void *a)
1414{
1415 unsigned long flags;
1416
1417 P9_DPRINTK(P9_DEBUG_MUX, "start %p\n", current);
1418 repeat:
1419 spin_lock_irqsave(&p9_poll_lock, flags);
1420 while (!list_empty(&p9_poll_pending_list)) {
1421 struct p9_conn *conn = list_first_entry(&p9_poll_pending_list,
1422 struct p9_conn,
1423 poll_pending_link);
1424 list_del_init(&conn->poll_pending_link);
1425 spin_unlock_irqrestore(&p9_poll_lock, flags);
1426
1427 p9_poll_mux(conn);
1428
1429 spin_lock_irqsave(&p9_poll_lock, flags);
1430 }
1431 spin_unlock_irqrestore(&p9_poll_lock, flags);
1432
1433 set_current_state(TASK_INTERRUPTIBLE);
1434 if (list_empty(&p9_poll_pending_list)) {
1435 P9_DPRINTK(P9_DEBUG_MUX, "sleeping...\n");
1436 schedule();
1437 }
1438 __set_current_state(TASK_RUNNING);
1439
1440 if (!kthread_should_stop())
1441 goto repeat;
1442
1443 P9_DPRINTK(P9_DEBUG_MUX, "finish\n");
1444 return 0;
1445}
1446
1495int p9_trans_fd_init(void) 1447int p9_trans_fd_init(void)
1496{ 1448{
1497 p9_mux_wq = create_workqueue("v9fs"); 1449 p9_mux_wq = create_workqueue("v9fs");