9P2010.L handshake: Add mount option
[linux-2.6.git] / net / 9p / client.c
1 /*
2  * net/9p/clnt.c
3  *
4  * 9P Client
5  *
6  *  Copyright (C) 2008 by Eric Van Hensbergen <ericvh@gmail.com>
7  *  Copyright (C) 2007 by Latchesar Ionkov <lucho@ionkov.net>
8  *
9  *  This program is free software; you can redistribute it and/or modify
10  *  it under the terms of the GNU General Public License version 2
11  *  as published by the Free Software Foundation.
12  *
13  *  This program is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  *
18  *  You should have received a copy of the GNU General Public License
19  *  along with this program; if not, write to:
20  *  Free Software Foundation
21  *  51 Franklin Street, Fifth Floor
22  *  Boston, MA  02111-1301  USA
23  *
24  */
25
26 #include <linux/module.h>
27 #include <linux/errno.h>
28 #include <linux/fs.h>
29 #include <linux/poll.h>
30 #include <linux/idr.h>
31 #include <linux/mutex.h>
32 #include <linux/sched.h>
33 #include <linux/uaccess.h>
34 #include <net/9p/9p.h>
35 #include <linux/parser.h>
36 #include <net/9p/client.h>
37 #include <net/9p/transport.h>
38 #include "protocol.h"
39
40 /*
41   * Client Option Parsing (code inspired by NFS code)
42   *  - a little lazy - parse all client options
43   */
44
45 enum {
46         Opt_msize,
47         Opt_trans,
48         Opt_legacy,
49         Opt_version,
50         Opt_err,
51 };
52
53 static const match_table_t tokens = {
54         {Opt_msize, "msize=%u"},
55         {Opt_legacy, "noextend"},
56         {Opt_trans, "trans=%s"},
57         {Opt_version, "version=%s"},
58         {Opt_err, NULL},
59 };
60
61 /* Interpret mount option for protocol version */
62 static unsigned char get_protocol_version(const substring_t *name)
63 {
64         unsigned char version = -EINVAL;
65         if (!strncmp("9p2000", name->from, name->to-name->from)) {
66                 version = p9_proto_legacy;
67                 P9_DPRINTK(P9_DEBUG_9P, "Protocol version: Legacy\n");
68         } else if (!strncmp("9p2000.u", name->from, name->to-name->from)) {
69                 version = p9_proto_2000u;
70                 P9_DPRINTK(P9_DEBUG_9P, "Protocol version: 9P2000.u\n");
71         } else if (!strncmp("9p2010.L", name->from, name->to-name->from)) {
72                 version = p9_proto_2010L;
73                 P9_DPRINTK(P9_DEBUG_9P, "Protocol version: 9P2010.L\n");
74         } else {
75                 P9_DPRINTK(P9_DEBUG_ERROR, "Unknown protocol version %s. ",
76                                                         name->from);
77         }
78         return version;
79 }
80
81 static struct p9_req_t *
82 p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...);
83
84 /**
85  * parse_options - parse mount options into client structure
86  * @opts: options string passed from mount
87  * @clnt: existing v9fs client information
88  *
89  * Return 0 upon success, -ERRNO upon failure
90  */
91
92 static int parse_opts(char *opts, struct p9_client *clnt)
93 {
94         char *options, *tmp_options;
95         char *p;
96         substring_t args[MAX_OPT_ARGS];
97         int option;
98         int ret = 0;
99
100         clnt->dotu = 1;
101         clnt->msize = 8192;
102
103         if (!opts)
104                 return 0;
105
106         tmp_options = kstrdup(opts, GFP_KERNEL);
107         if (!tmp_options) {
108                 P9_DPRINTK(P9_DEBUG_ERROR,
109                                 "failed to allocate copy of option string\n");
110                 return -ENOMEM;
111         }
112         options = tmp_options;
113
114         while ((p = strsep(&options, ",")) != NULL) {
115                 int token;
116                 if (!*p)
117                         continue;
118                 token = match_token(p, tokens, args);
119                 if (token < Opt_trans) {
120                         int r = match_int(&args[0], &option);
121                         if (r < 0) {
122                                 P9_DPRINTK(P9_DEBUG_ERROR,
123                                         "integer field, but no integer?\n");
124                                 ret = r;
125                                 continue;
126                         }
127                 }
128                 switch (token) {
129                 case Opt_msize:
130                         clnt->msize = option;
131                         break;
132                 case Opt_trans:
133                         clnt->trans_mod = v9fs_get_trans_by_name(&args[0]);
134                         if(clnt->trans_mod == NULL) {
135                                 P9_DPRINTK(P9_DEBUG_ERROR,
136                                    "Could not find request transport: %s\n",
137                                    (char *) &args[0]);
138                                 ret = -EINVAL;
139                                 goto free_and_return;
140                         }
141                         break;
142                 case Opt_legacy:
143                         clnt->dotu = 0;
144                         break;
145                 case Opt_version:
146                         ret = get_protocol_version(&args[0]);
147                         if (ret == -EINVAL)
148                                 goto free_and_return;
149                         clnt->proto_version = ret;
150                         break;
151                 default:
152                         continue;
153                 }
154         }
155
156 free_and_return:
157         kfree(tmp_options);
158         return ret;
159 }
160
161 /**
162  * p9_tag_alloc - lookup/allocate a request by tag
163  * @c: client session to lookup tag within
164  * @tag: numeric id for transaction
165  *
166  * this is a simple array lookup, but will grow the
167  * request_slots as necessary to accomodate transaction
168  * ids which did not previously have a slot.
169  *
170  * this code relies on the client spinlock to manage locks, its
171  * possible we should switch to something else, but I'd rather
172  * stick with something low-overhead for the common case.
173  *
174  */
175
176 static struct p9_req_t *p9_tag_alloc(struct p9_client *c, u16 tag)
177 {
178         unsigned long flags;
179         int row, col;
180         struct p9_req_t *req;
181
182         /* This looks up the original request by tag so we know which
183          * buffer to read the data into */
184         tag++;
185
186         if (tag >= c->max_tag) {
187                 spin_lock_irqsave(&c->lock, flags);
188                 /* check again since original check was outside of lock */
189                 while (tag >= c->max_tag) {
190                         row = (tag / P9_ROW_MAXTAG);
191                         c->reqs[row] = kcalloc(P9_ROW_MAXTAG,
192                                         sizeof(struct p9_req_t), GFP_ATOMIC);
193
194                         if (!c->reqs[row]) {
195                                 printk(KERN_ERR "Couldn't grow tag array\n");
196                                 spin_unlock_irqrestore(&c->lock, flags);
197                                 return ERR_PTR(-ENOMEM);
198                         }
199                         for (col = 0; col < P9_ROW_MAXTAG; col++) {
200                                 c->reqs[row][col].status = REQ_STATUS_IDLE;
201                                 c->reqs[row][col].tc = NULL;
202                         }
203                         c->max_tag += P9_ROW_MAXTAG;
204                 }
205                 spin_unlock_irqrestore(&c->lock, flags);
206         }
207         row = tag / P9_ROW_MAXTAG;
208         col = tag % P9_ROW_MAXTAG;
209
210         req = &c->reqs[row][col];
211         if (!req->tc) {
212                 req->wq = kmalloc(sizeof(wait_queue_head_t), GFP_KERNEL);
213                 if (!req->wq) {
214                         printk(KERN_ERR "Couldn't grow tag array\n");
215                         return ERR_PTR(-ENOMEM);
216                 }
217                 init_waitqueue_head(req->wq);
218                 req->tc = kmalloc(sizeof(struct p9_fcall)+c->msize,
219                                                                 GFP_KERNEL);
220                 req->rc = kmalloc(sizeof(struct p9_fcall)+c->msize,
221                                                                 GFP_KERNEL);
222                 if ((!req->tc) || (!req->rc)) {
223                         printk(KERN_ERR "Couldn't grow tag array\n");
224                         kfree(req->tc);
225                         kfree(req->rc);
226                         kfree(req->wq);
227                         req->tc = req->rc = NULL;
228                         req->wq = NULL;
229                         return ERR_PTR(-ENOMEM);
230                 }
231                 req->tc->sdata = (char *) req->tc + sizeof(struct p9_fcall);
232                 req->tc->capacity = c->msize;
233                 req->rc->sdata = (char *) req->rc + sizeof(struct p9_fcall);
234                 req->rc->capacity = c->msize;
235         }
236
237         p9pdu_reset(req->tc);
238         p9pdu_reset(req->rc);
239
240         req->tc->tag = tag-1;
241         req->status = REQ_STATUS_ALLOC;
242
243         return &c->reqs[row][col];
244 }
245
246 /**
247  * p9_tag_lookup - lookup a request by tag
248  * @c: client session to lookup tag within
249  * @tag: numeric id for transaction
250  *
251  */
252
253 struct p9_req_t *p9_tag_lookup(struct p9_client *c, u16 tag)
254 {
255         int row, col;
256
257         /* This looks up the original request by tag so we know which
258          * buffer to read the data into */
259         tag++;
260
261         BUG_ON(tag >= c->max_tag);
262
263         row = tag / P9_ROW_MAXTAG;
264         col = tag % P9_ROW_MAXTAG;
265
266         return &c->reqs[row][col];
267 }
268 EXPORT_SYMBOL(p9_tag_lookup);
269
270 /**
271  * p9_tag_init - setup tags structure and contents
272  * @c:  v9fs client struct
273  *
274  * This initializes the tags structure for each client instance.
275  *
276  */
277
278 static int p9_tag_init(struct p9_client *c)
279 {
280         int err = 0;
281
282         c->tagpool = p9_idpool_create();
283         if (IS_ERR(c->tagpool)) {
284                 err = PTR_ERR(c->tagpool);
285                 c->tagpool = NULL;
286                 goto error;
287         }
288
289         p9_idpool_get(c->tagpool); /* reserve tag 0 */
290
291         c->max_tag = 0;
292 error:
293         return err;
294 }
295
296 /**
297  * p9_tag_cleanup - cleans up tags structure and reclaims resources
298  * @c:  v9fs client struct
299  *
300  * This frees resources associated with the tags structure
301  *
302  */
303 static void p9_tag_cleanup(struct p9_client *c)
304 {
305         int row, col;
306
307         /* check to insure all requests are idle */
308         for (row = 0; row < (c->max_tag/P9_ROW_MAXTAG); row++) {
309                 for (col = 0; col < P9_ROW_MAXTAG; col++) {
310                         if (c->reqs[row][col].status != REQ_STATUS_IDLE) {
311                                 P9_DPRINTK(P9_DEBUG_MUX,
312                                   "Attempting to cleanup non-free tag %d,%d\n",
313                                   row, col);
314                                 /* TODO: delay execution of cleanup */
315                                 return;
316                         }
317                 }
318         }
319
320         if (c->tagpool)
321                 p9_idpool_destroy(c->tagpool);
322
323         /* free requests associated with tags */
324         for (row = 0; row < (c->max_tag/P9_ROW_MAXTAG); row++) {
325                 for (col = 0; col < P9_ROW_MAXTAG; col++) {
326                         kfree(c->reqs[row][col].wq);
327                         kfree(c->reqs[row][col].tc);
328                         kfree(c->reqs[row][col].rc);
329                 }
330                 kfree(c->reqs[row]);
331         }
332         c->max_tag = 0;
333 }
334
335 /**
336  * p9_free_req - free a request and clean-up as necessary
337  * c: client state
338  * r: request to release
339  *
340  */
341
342 static void p9_free_req(struct p9_client *c, struct p9_req_t *r)
343 {
344         int tag = r->tc->tag;
345         P9_DPRINTK(P9_DEBUG_MUX, "clnt %p req %p tag: %d\n", c, r, tag);
346
347         r->status = REQ_STATUS_IDLE;
348         if (tag != P9_NOTAG && p9_idpool_check(tag, c->tagpool))
349                 p9_idpool_put(tag, c->tagpool);
350 }
351
352 /**
353  * p9_client_cb - call back from transport to client
354  * c: client state
355  * req: request received
356  *
357  */
358 void p9_client_cb(struct p9_client *c, struct p9_req_t *req)
359 {
360         P9_DPRINTK(P9_DEBUG_MUX, " tag %d\n", req->tc->tag);
361         wake_up(req->wq);
362         P9_DPRINTK(P9_DEBUG_MUX, "wakeup: %d\n", req->tc->tag);
363 }
364 EXPORT_SYMBOL(p9_client_cb);
365
366 /**
367  * p9_parse_header - parse header arguments out of a packet
368  * @pdu: packet to parse
369  * @size: size of packet
370  * @type: type of request
371  * @tag: tag of packet
372  * @rewind: set if we need to rewind offset afterwards
373  */
374
375 int
376 p9_parse_header(struct p9_fcall *pdu, int32_t *size, int8_t *type, int16_t *tag,
377                                                                 int rewind)
378 {
379         int8_t r_type;
380         int16_t r_tag;
381         int32_t r_size;
382         int offset = pdu->offset;
383         int err;
384
385         pdu->offset = 0;
386         if (pdu->size == 0)
387                 pdu->size = 7;
388
389         err = p9pdu_readf(pdu, 0, "dbw", &r_size, &r_type, &r_tag);
390         if (err)
391                 goto rewind_and_exit;
392
393         pdu->size = r_size;
394         pdu->id = r_type;
395         pdu->tag = r_tag;
396
397         P9_DPRINTK(P9_DEBUG_9P, "<<< size=%d type: %d tag: %d\n", pdu->size,
398                                                         pdu->id, pdu->tag);
399
400         if (type)
401                 *type = r_type;
402         if (tag)
403                 *tag = r_tag;
404         if (size)
405                 *size = r_size;
406
407
408 rewind_and_exit:
409         if (rewind)
410                 pdu->offset = offset;
411         return err;
412 }
413 EXPORT_SYMBOL(p9_parse_header);
414
415 /**
416  * p9_check_errors - check 9p packet for error return and process it
417  * @c: current client instance
418  * @req: request to parse and check for error conditions
419  *
420  * returns error code if one is discovered, otherwise returns 0
421  *
422  * this will have to be more complicated if we have multiple
423  * error packet types
424  */
425
426 static int p9_check_errors(struct p9_client *c, struct p9_req_t *req)
427 {
428         int8_t type;
429         int err;
430
431         err = p9_parse_header(req->rc, NULL, &type, NULL, 0);
432         if (err) {
433                 P9_DPRINTK(P9_DEBUG_ERROR, "couldn't parse header %d\n", err);
434                 return err;
435         }
436
437         if (type == P9_RERROR) {
438                 int ecode;
439                 char *ename;
440
441                 err = p9pdu_readf(req->rc, c->dotu, "s?d", &ename, &ecode);
442                 if (err) {
443                         P9_DPRINTK(P9_DEBUG_ERROR, "couldn't parse error%d\n",
444                                                                         err);
445                         return err;
446                 }
447
448                 if (c->dotu)
449                         err = -ecode;
450
451                 if (!err || !IS_ERR_VALUE(err))
452                         err = p9_errstr2errno(ename, strlen(ename));
453
454                 P9_DPRINTK(P9_DEBUG_9P, "<<< RERROR (%d) %s\n", -ecode, ename);
455
456                 kfree(ename);
457         } else
458                 err = 0;
459
460         return err;
461 }
462
463 /**
464  * p9_client_flush - flush (cancel) a request
465  * @c: client state
466  * @oldreq: request to cancel
467  *
468  * This sents a flush for a particular requests and links
469  * the flush request to the original request.  The current
470  * code only supports a single flush request although the protocol
471  * allows for multiple flush requests to be sent for a single request.
472  *
473  */
474
475 static int p9_client_flush(struct p9_client *c, struct p9_req_t *oldreq)
476 {
477         struct p9_req_t *req;
478         int16_t oldtag;
479         int err;
480
481         err = p9_parse_header(oldreq->tc, NULL, NULL, &oldtag, 1);
482         if (err)
483                 return err;
484
485         P9_DPRINTK(P9_DEBUG_9P, ">>> TFLUSH tag %d\n", oldtag);
486
487         req = p9_client_rpc(c, P9_TFLUSH, "w", oldtag);
488         if (IS_ERR(req))
489                 return PTR_ERR(req);
490
491
492         /* if we haven't received a response for oldreq,
493            remove it from the list. */
494         spin_lock(&c->lock);
495         if (oldreq->status == REQ_STATUS_FLSH)
496                 list_del(&oldreq->req_list);
497         spin_unlock(&c->lock);
498
499         p9_free_req(c, req);
500         return 0;
501 }
502
503 /**
504  * p9_client_rpc - issue a request and wait for a response
505  * @c: client session
506  * @type: type of request
507  * @fmt: protocol format string (see protocol.c)
508  *
509  * Returns request structure (which client must free using p9_free_req)
510  */
511
512 static struct p9_req_t *
513 p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...)
514 {
515         va_list ap;
516         int tag, err;
517         struct p9_req_t *req;
518         unsigned long flags;
519         int sigpending;
520
521         P9_DPRINTK(P9_DEBUG_MUX, "client %p op %d\n", c, type);
522
523         if (c->status != Connected)
524                 return ERR_PTR(-EIO);
525
526         if (signal_pending(current)) {
527                 sigpending = 1;
528                 clear_thread_flag(TIF_SIGPENDING);
529         } else
530                 sigpending = 0;
531
532         tag = P9_NOTAG;
533         if (type != P9_TVERSION) {
534                 tag = p9_idpool_get(c->tagpool);
535                 if (tag < 0)
536                         return ERR_PTR(-ENOMEM);
537         }
538
539         req = p9_tag_alloc(c, tag);
540         if (IS_ERR(req))
541                 return req;
542
543         /* marshall the data */
544         p9pdu_prepare(req->tc, tag, type);
545         va_start(ap, fmt);
546         err = p9pdu_vwritef(req->tc, c->dotu, fmt, ap);
547         va_end(ap);
548         p9pdu_finalize(req->tc);
549
550         err = c->trans_mod->request(c, req);
551         if (err < 0) {
552                 c->status = Disconnected;
553                 goto reterr;
554         }
555
556         P9_DPRINTK(P9_DEBUG_MUX, "wait %p tag: %d\n", req->wq, tag);
557         err = wait_event_interruptible(*req->wq,
558                                                 req->status >= REQ_STATUS_RCVD);
559         P9_DPRINTK(P9_DEBUG_MUX, "wait %p tag: %d returned %d\n",
560                                                 req->wq, tag, err);
561
562         if (req->status == REQ_STATUS_ERROR) {
563                 P9_DPRINTK(P9_DEBUG_ERROR, "req_status error %d\n", req->t_err);
564                 err = req->t_err;
565         }
566
567         if ((err == -ERESTARTSYS) && (c->status == Connected)) {
568                 P9_DPRINTK(P9_DEBUG_MUX, "flushing\n");
569                 sigpending = 1;
570                 clear_thread_flag(TIF_SIGPENDING);
571
572                 if (c->trans_mod->cancel(c, req))
573                         p9_client_flush(c, req);
574
575                 /* if we received the response anyway, don't signal error */
576                 if (req->status == REQ_STATUS_RCVD)
577                         err = 0;
578         }
579
580         if (sigpending) {
581                 spin_lock_irqsave(&current->sighand->siglock, flags);
582                 recalc_sigpending();
583                 spin_unlock_irqrestore(&current->sighand->siglock, flags);
584         }
585
586         if (err < 0)
587                 goto reterr;
588
589         err = p9_check_errors(c, req);
590         if (!err) {
591                 P9_DPRINTK(P9_DEBUG_MUX, "exit: client %p op %d\n", c, type);
592                 return req;
593         }
594
595 reterr:
596         P9_DPRINTK(P9_DEBUG_MUX, "exit: client %p op %d error: %d\n", c, type,
597                                                                         err);
598         p9_free_req(c, req);
599         return ERR_PTR(err);
600 }
601
602 static struct p9_fid *p9_fid_create(struct p9_client *clnt)
603 {
604         int ret;
605         struct p9_fid *fid;
606         unsigned long flags;
607
608         P9_DPRINTK(P9_DEBUG_FID, "clnt %p\n", clnt);
609         fid = kmalloc(sizeof(struct p9_fid), GFP_KERNEL);
610         if (!fid)
611                 return ERR_PTR(-ENOMEM);
612
613         ret = p9_idpool_get(clnt->fidpool);
614         if (ret < 0) {
615                 ret = -ENOSPC;
616                 goto error;
617         }
618         fid->fid = ret;
619
620         memset(&fid->qid, 0, sizeof(struct p9_qid));
621         fid->mode = -1;
622         fid->uid = current_fsuid();
623         fid->clnt = clnt;
624         fid->rdir = NULL;
625         spin_lock_irqsave(&clnt->lock, flags);
626         list_add(&fid->flist, &clnt->fidlist);
627         spin_unlock_irqrestore(&clnt->lock, flags);
628
629         return fid;
630
631 error:
632         kfree(fid);
633         return ERR_PTR(ret);
634 }
635
636 static void p9_fid_destroy(struct p9_fid *fid)
637 {
638         struct p9_client *clnt;
639         unsigned long flags;
640
641         P9_DPRINTK(P9_DEBUG_FID, "fid %d\n", fid->fid);
642         clnt = fid->clnt;
643         p9_idpool_put(fid->fid, clnt->fidpool);
644         spin_lock_irqsave(&clnt->lock, flags);
645         list_del(&fid->flist);
646         spin_unlock_irqrestore(&clnt->lock, flags);
647         kfree(fid->rdir);
648         kfree(fid);
649 }
650
651 int p9_client_version(struct p9_client *c)
652 {
653         int err = 0;
654         struct p9_req_t *req;
655         char *version;
656         int msize;
657
658         P9_DPRINTK(P9_DEBUG_9P, ">>> TVERSION msize %d extended %d\n",
659                                                         c->msize, c->dotu);
660         req = p9_client_rpc(c, P9_TVERSION, "ds", c->msize,
661                                 c->dotu ? "9P2000.u" : "9P2000");
662         if (IS_ERR(req))
663                 return PTR_ERR(req);
664
665         err = p9pdu_readf(req->rc, c->dotu, "ds", &msize, &version);
666         if (err) {
667                 P9_DPRINTK(P9_DEBUG_9P, "version error %d\n", err);
668                 p9pdu_dump(1, req->rc);
669                 goto error;
670         }
671
672         P9_DPRINTK(P9_DEBUG_9P, "<<< RVERSION msize %d %s\n", msize, version);
673         if (!memcmp(version, "9P2000.u", 8))
674                 c->dotu = 1;
675         else if (!memcmp(version, "9P2000", 6))
676                 c->dotu = 0;
677         else {
678                 err = -EREMOTEIO;
679                 goto error;
680         }
681
682         if (msize < c->msize)
683                 c->msize = msize;
684
685 error:
686         kfree(version);
687         p9_free_req(c, req);
688
689         return err;
690 }
691 EXPORT_SYMBOL(p9_client_version);
692
693 struct p9_client *p9_client_create(const char *dev_name, char *options)
694 {
695         int err;
696         struct p9_client *clnt;
697
698         err = 0;
699         clnt = kmalloc(sizeof(struct p9_client), GFP_KERNEL);
700         if (!clnt)
701                 return ERR_PTR(-ENOMEM);
702
703         clnt->trans_mod = NULL;
704         clnt->trans = NULL;
705         spin_lock_init(&clnt->lock);
706         INIT_LIST_HEAD(&clnt->fidlist);
707
708         p9_tag_init(clnt);
709
710         err = parse_opts(options, clnt);
711         if (err < 0)
712                 goto free_client;
713
714         if (!clnt->trans_mod)
715                 clnt->trans_mod = v9fs_get_default_trans();
716
717         if (clnt->trans_mod == NULL) {
718                 err = -EPROTONOSUPPORT;
719                 P9_DPRINTK(P9_DEBUG_ERROR,
720                                 "No transport defined or default transport\n");
721                 goto free_client;
722         }
723
724         clnt->fidpool = p9_idpool_create();
725         if (IS_ERR(clnt->fidpool)) {
726                 err = PTR_ERR(clnt->fidpool);
727                 clnt->fidpool = NULL;
728                 goto put_trans;
729         }
730
731         P9_DPRINTK(P9_DEBUG_MUX, "clnt %p trans %p msize %d dotu %d\n",
732                 clnt, clnt->trans_mod, clnt->msize, clnt->dotu);
733
734         err = clnt->trans_mod->create(clnt, dev_name, options);
735         if (err)
736                 goto destroy_fidpool;
737
738         if ((clnt->msize+P9_IOHDRSZ) > clnt->trans_mod->maxsize)
739                 clnt->msize = clnt->trans_mod->maxsize-P9_IOHDRSZ;
740
741         err = p9_client_version(clnt);
742         if (err)
743                 goto close_trans;
744
745         return clnt;
746
747 close_trans:
748         clnt->trans_mod->close(clnt);
749 destroy_fidpool:
750         p9_idpool_destroy(clnt->fidpool);
751 put_trans:
752         v9fs_put_trans(clnt->trans_mod);
753 free_client:
754         kfree(clnt);
755         return ERR_PTR(err);
756 }
757 EXPORT_SYMBOL(p9_client_create);
758
759 void p9_client_destroy(struct p9_client *clnt)
760 {
761         struct p9_fid *fid, *fidptr;
762
763         P9_DPRINTK(P9_DEBUG_MUX, "clnt %p\n", clnt);
764
765         if (clnt->trans_mod)
766                 clnt->trans_mod->close(clnt);
767
768         v9fs_put_trans(clnt->trans_mod);
769
770         list_for_each_entry_safe(fid, fidptr, &clnt->fidlist, flist)
771                 p9_fid_destroy(fid);
772
773         if (clnt->fidpool)
774                 p9_idpool_destroy(clnt->fidpool);
775
776         p9_tag_cleanup(clnt);
777
778         kfree(clnt);
779 }
780 EXPORT_SYMBOL(p9_client_destroy);
781
782 void p9_client_disconnect(struct p9_client *clnt)
783 {
784         P9_DPRINTK(P9_DEBUG_9P, "clnt %p\n", clnt);
785         clnt->status = Disconnected;
786 }
787 EXPORT_SYMBOL(p9_client_disconnect);
788
789 struct p9_fid *p9_client_attach(struct p9_client *clnt, struct p9_fid *afid,
790         char *uname, u32 n_uname, char *aname)
791 {
792         int err;
793         struct p9_req_t *req;
794         struct p9_fid *fid;
795         struct p9_qid qid;
796
797         P9_DPRINTK(P9_DEBUG_9P, ">>> TATTACH afid %d uname %s aname %s\n",
798                                         afid ? afid->fid : -1, uname, aname);
799         err = 0;
800
801         fid = p9_fid_create(clnt);
802         if (IS_ERR(fid)) {
803                 err = PTR_ERR(fid);
804                 fid = NULL;
805                 goto error;
806         }
807
808         req = p9_client_rpc(clnt, P9_TATTACH, "ddss?d", fid->fid,
809                         afid ? afid->fid : P9_NOFID, uname, aname, n_uname);
810         if (IS_ERR(req)) {
811                 err = PTR_ERR(req);
812                 goto error;
813         }
814
815         err = p9pdu_readf(req->rc, clnt->dotu, "Q", &qid);
816         if (err) {
817                 p9pdu_dump(1, req->rc);
818                 p9_free_req(clnt, req);
819                 goto error;
820         }
821
822         P9_DPRINTK(P9_DEBUG_9P, "<<< RATTACH qid %x.%llx.%x\n",
823                                         qid.type,
824                                         (unsigned long long)qid.path,
825                                         qid.version);
826
827         memmove(&fid->qid, &qid, sizeof(struct p9_qid));
828
829         p9_free_req(clnt, req);
830         return fid;
831
832 error:
833         if (fid)
834                 p9_fid_destroy(fid);
835         return ERR_PTR(err);
836 }
837 EXPORT_SYMBOL(p9_client_attach);
838
839 struct p9_fid *
840 p9_client_auth(struct p9_client *clnt, char *uname, u32 n_uname, char *aname)
841 {
842         int err;
843         struct p9_req_t *req;
844         struct p9_qid qid;
845         struct p9_fid *afid;
846
847         P9_DPRINTK(P9_DEBUG_9P, ">>> TAUTH uname %s aname %s\n", uname, aname);
848         err = 0;
849
850         afid = p9_fid_create(clnt);
851         if (IS_ERR(afid)) {
852                 err = PTR_ERR(afid);
853                 afid = NULL;
854                 goto error;
855         }
856
857         req = p9_client_rpc(clnt, P9_TAUTH, "dss?d",
858                         afid ? afid->fid : P9_NOFID, uname, aname, n_uname);
859         if (IS_ERR(req)) {
860                 err = PTR_ERR(req);
861                 goto error;
862         }
863
864         err = p9pdu_readf(req->rc, clnt->dotu, "Q", &qid);
865         if (err) {
866                 p9pdu_dump(1, req->rc);
867                 p9_free_req(clnt, req);
868                 goto error;
869         }
870
871         P9_DPRINTK(P9_DEBUG_9P, "<<< RAUTH qid %x.%llx.%x\n",
872                                         qid.type,
873                                         (unsigned long long)qid.path,
874                                         qid.version);
875
876         memmove(&afid->qid, &qid, sizeof(struct p9_qid));
877         p9_free_req(clnt, req);
878         return afid;
879
880 error:
881         if (afid)
882                 p9_fid_destroy(afid);
883         return ERR_PTR(err);
884 }
885 EXPORT_SYMBOL(p9_client_auth);
886
887 struct p9_fid *p9_client_walk(struct p9_fid *oldfid, int nwname, char **wnames,
888         int clone)
889 {
890         int err;
891         struct p9_client *clnt;
892         struct p9_fid *fid;
893         struct p9_qid *wqids;
894         struct p9_req_t *req;
895         int16_t nwqids, count;
896
897         err = 0;
898         clnt = oldfid->clnt;
899         if (clone) {
900                 fid = p9_fid_create(clnt);
901                 if (IS_ERR(fid)) {
902                         err = PTR_ERR(fid);
903                         fid = NULL;
904                         goto error;
905                 }
906
907                 fid->uid = oldfid->uid;
908         } else
909                 fid = oldfid;
910
911
912         P9_DPRINTK(P9_DEBUG_9P, ">>> TWALK fids %d,%d nwname %d wname[0] %s\n",
913                 oldfid->fid, fid->fid, nwname, wnames ? wnames[0] : NULL);
914
915         req = p9_client_rpc(clnt, P9_TWALK, "ddT", oldfid->fid, fid->fid,
916                                                                 nwname, wnames);
917         if (IS_ERR(req)) {
918                 err = PTR_ERR(req);
919                 goto error;
920         }
921
922         err = p9pdu_readf(req->rc, clnt->dotu, "R", &nwqids, &wqids);
923         if (err) {
924                 p9pdu_dump(1, req->rc);
925                 p9_free_req(clnt, req);
926                 goto clunk_fid;
927         }
928         p9_free_req(clnt, req);
929
930         P9_DPRINTK(P9_DEBUG_9P, "<<< RWALK nwqid %d:\n", nwqids);
931
932         if (nwqids != nwname) {
933                 err = -ENOENT;
934                 goto clunk_fid;
935         }
936
937         for (count = 0; count < nwqids; count++)
938                 P9_DPRINTK(P9_DEBUG_9P, "<<<     [%d] %x.%llx.%x\n",
939                         count, wqids[count].type,
940                         (unsigned long long)wqids[count].path,
941                         wqids[count].version);
942
943         if (nwname)
944                 memmove(&fid->qid, &wqids[nwqids - 1], sizeof(struct p9_qid));
945         else
946                 fid->qid = oldfid->qid;
947
948         return fid;
949
950 clunk_fid:
951         p9_client_clunk(fid);
952         fid = NULL;
953
954 error:
955         if (fid && (fid != oldfid))
956                 p9_fid_destroy(fid);
957
958         return ERR_PTR(err);
959 }
960 EXPORT_SYMBOL(p9_client_walk);
961
962 int p9_client_open(struct p9_fid *fid, int mode)
963 {
964         int err;
965         struct p9_client *clnt;
966         struct p9_req_t *req;
967         struct p9_qid qid;
968         int iounit;
969
970         P9_DPRINTK(P9_DEBUG_9P, ">>> TOPEN fid %d mode %d\n", fid->fid, mode);
971         err = 0;
972         clnt = fid->clnt;
973
974         if (fid->mode != -1)
975                 return -EINVAL;
976
977         req = p9_client_rpc(clnt, P9_TOPEN, "db", fid->fid, mode);
978         if (IS_ERR(req)) {
979                 err = PTR_ERR(req);
980                 goto error;
981         }
982
983         err = p9pdu_readf(req->rc, clnt->dotu, "Qd", &qid, &iounit);
984         if (err) {
985                 p9pdu_dump(1, req->rc);
986                 goto free_and_error;
987         }
988
989         P9_DPRINTK(P9_DEBUG_9P, "<<< ROPEN qid %x.%llx.%x iounit %x\n",
990                                 qid.type,
991                                 (unsigned long long)qid.path,
992                                 qid.version, iounit);
993
994         fid->mode = mode;
995         fid->iounit = iounit;
996
997 free_and_error:
998         p9_free_req(clnt, req);
999 error:
1000         return err;
1001 }
1002 EXPORT_SYMBOL(p9_client_open);
1003
1004 int p9_client_fcreate(struct p9_fid *fid, char *name, u32 perm, int mode,
1005                      char *extension)
1006 {
1007         int err;
1008         struct p9_client *clnt;
1009         struct p9_req_t *req;
1010         struct p9_qid qid;
1011         int iounit;
1012
1013         P9_DPRINTK(P9_DEBUG_9P, ">>> TCREATE fid %d name %s perm %d mode %d\n",
1014                                                 fid->fid, name, perm, mode);
1015         err = 0;
1016         clnt = fid->clnt;
1017
1018         if (fid->mode != -1)
1019                 return -EINVAL;
1020
1021         req = p9_client_rpc(clnt, P9_TCREATE, "dsdb?s", fid->fid, name, perm,
1022                                 mode, extension);
1023         if (IS_ERR(req)) {
1024                 err = PTR_ERR(req);
1025                 goto error;
1026         }
1027
1028         err = p9pdu_readf(req->rc, clnt->dotu, "Qd", &qid, &iounit);
1029         if (err) {
1030                 p9pdu_dump(1, req->rc);
1031                 goto free_and_error;
1032         }
1033
1034         P9_DPRINTK(P9_DEBUG_9P, "<<< RCREATE qid %x.%llx.%x iounit %x\n",
1035                                 qid.type,
1036                                 (unsigned long long)qid.path,
1037                                 qid.version, iounit);
1038
1039         fid->mode = mode;
1040         fid->iounit = iounit;
1041
1042 free_and_error:
1043         p9_free_req(clnt, req);
1044 error:
1045         return err;
1046 }
1047 EXPORT_SYMBOL(p9_client_fcreate);
1048
1049 int p9_client_clunk(struct p9_fid *fid)
1050 {
1051         int err;
1052         struct p9_client *clnt;
1053         struct p9_req_t *req;
1054
1055         P9_DPRINTK(P9_DEBUG_9P, ">>> TCLUNK fid %d\n", fid->fid);
1056         err = 0;
1057         clnt = fid->clnt;
1058
1059         req = p9_client_rpc(clnt, P9_TCLUNK, "d", fid->fid);
1060         if (IS_ERR(req)) {
1061                 err = PTR_ERR(req);
1062                 goto error;
1063         }
1064
1065         P9_DPRINTK(P9_DEBUG_9P, "<<< RCLUNK fid %d\n", fid->fid);
1066
1067         p9_free_req(clnt, req);
1068         p9_fid_destroy(fid);
1069
1070 error:
1071         return err;
1072 }
1073 EXPORT_SYMBOL(p9_client_clunk);
1074
1075 int p9_client_remove(struct p9_fid *fid)
1076 {
1077         int err;
1078         struct p9_client *clnt;
1079         struct p9_req_t *req;
1080
1081         P9_DPRINTK(P9_DEBUG_9P, ">>> TREMOVE fid %d\n", fid->fid);
1082         err = 0;
1083         clnt = fid->clnt;
1084
1085         req = p9_client_rpc(clnt, P9_TREMOVE, "d", fid->fid);
1086         if (IS_ERR(req)) {
1087                 err = PTR_ERR(req);
1088                 goto error;
1089         }
1090
1091         P9_DPRINTK(P9_DEBUG_9P, "<<< RREMOVE fid %d\n", fid->fid);
1092
1093         p9_free_req(clnt, req);
1094         p9_fid_destroy(fid);
1095
1096 error:
1097         return err;
1098 }
1099 EXPORT_SYMBOL(p9_client_remove);
1100
1101 int
1102 p9_client_read(struct p9_fid *fid, char *data, char __user *udata, u64 offset,
1103                                                                 u32 count)
1104 {
1105         int err, rsize, total;
1106         struct p9_client *clnt;
1107         struct p9_req_t *req;
1108         char *dataptr;
1109
1110         P9_DPRINTK(P9_DEBUG_9P, ">>> TREAD fid %d offset %llu %d\n", fid->fid,
1111                                         (long long unsigned) offset, count);
1112         err = 0;
1113         clnt = fid->clnt;
1114         total = 0;
1115
1116         rsize = fid->iounit;
1117         if (!rsize || rsize > clnt->msize-P9_IOHDRSZ)
1118                 rsize = clnt->msize - P9_IOHDRSZ;
1119
1120         if (count < rsize)
1121                 rsize = count;
1122
1123         req = p9_client_rpc(clnt, P9_TREAD, "dqd", fid->fid, offset, rsize);
1124         if (IS_ERR(req)) {
1125                 err = PTR_ERR(req);
1126                 goto error;
1127         }
1128
1129         err = p9pdu_readf(req->rc, clnt->dotu, "D", &count, &dataptr);
1130         if (err) {
1131                 p9pdu_dump(1, req->rc);
1132                 goto free_and_error;
1133         }
1134
1135         P9_DPRINTK(P9_DEBUG_9P, "<<< RREAD count %d\n", count);
1136
1137         if (data) {
1138                 memmove(data, dataptr, count);
1139         }
1140
1141         if (udata) {
1142                 err = copy_to_user(udata, dataptr, count);
1143                 if (err) {
1144                         err = -EFAULT;
1145                         goto free_and_error;
1146                 }
1147         }
1148
1149         p9_free_req(clnt, req);
1150         return count;
1151
1152 free_and_error:
1153         p9_free_req(clnt, req);
1154 error:
1155         return err;
1156 }
1157 EXPORT_SYMBOL(p9_client_read);
1158
1159 int
1160 p9_client_write(struct p9_fid *fid, char *data, const char __user *udata,
1161                                                         u64 offset, u32 count)
1162 {
1163         int err, rsize, total;
1164         struct p9_client *clnt;
1165         struct p9_req_t *req;
1166
1167         P9_DPRINTK(P9_DEBUG_9P, ">>> TWRITE fid %d offset %llu count %d\n",
1168                                 fid->fid, (long long unsigned) offset, count);
1169         err = 0;
1170         clnt = fid->clnt;
1171         total = 0;
1172
1173         rsize = fid->iounit;
1174         if (!rsize || rsize > clnt->msize-P9_IOHDRSZ)
1175                 rsize = clnt->msize - P9_IOHDRSZ;
1176
1177         if (count < rsize)
1178                 rsize = count;
1179         if (data)
1180                 req = p9_client_rpc(clnt, P9_TWRITE, "dqD", fid->fid, offset,
1181                                                                 rsize, data);
1182         else
1183                 req = p9_client_rpc(clnt, P9_TWRITE, "dqU", fid->fid, offset,
1184                                                                 rsize, udata);
1185         if (IS_ERR(req)) {
1186                 err = PTR_ERR(req);
1187                 goto error;
1188         }
1189
1190         err = p9pdu_readf(req->rc, clnt->dotu, "d", &count);
1191         if (err) {
1192                 p9pdu_dump(1, req->rc);
1193                 goto free_and_error;
1194         }
1195
1196         P9_DPRINTK(P9_DEBUG_9P, "<<< RWRITE count %d\n", count);
1197
1198         p9_free_req(clnt, req);
1199         return count;
1200
1201 free_and_error:
1202         p9_free_req(clnt, req);
1203 error:
1204         return err;
1205 }
1206 EXPORT_SYMBOL(p9_client_write);
1207
1208 struct p9_wstat *p9_client_stat(struct p9_fid *fid)
1209 {
1210         int err;
1211         struct p9_client *clnt;
1212         struct p9_wstat *ret = kmalloc(sizeof(struct p9_wstat), GFP_KERNEL);
1213         struct p9_req_t *req;
1214         u16 ignored;
1215
1216         P9_DPRINTK(P9_DEBUG_9P, ">>> TSTAT fid %d\n", fid->fid);
1217
1218         if (!ret)
1219                 return ERR_PTR(-ENOMEM);
1220
1221         err = 0;
1222         clnt = fid->clnt;
1223
1224         req = p9_client_rpc(clnt, P9_TSTAT, "d", fid->fid);
1225         if (IS_ERR(req)) {
1226                 err = PTR_ERR(req);
1227                 goto error;
1228         }
1229
1230         err = p9pdu_readf(req->rc, clnt->dotu, "wS", &ignored, ret);
1231         if (err) {
1232                 p9pdu_dump(1, req->rc);
1233                 p9_free_req(clnt, req);
1234                 goto error;
1235         }
1236
1237         P9_DPRINTK(P9_DEBUG_9P,
1238                 "<<< RSTAT sz=%x type=%x dev=%x qid=%x.%llx.%x\n"
1239                 "<<<    mode=%8.8x atime=%8.8x mtime=%8.8x length=%llx\n"
1240                 "<<<    name=%s uid=%s gid=%s muid=%s extension=(%s)\n"
1241                 "<<<    uid=%d gid=%d n_muid=%d\n",
1242                 ret->size, ret->type, ret->dev, ret->qid.type,
1243                 (unsigned long long)ret->qid.path, ret->qid.version, ret->mode,
1244                 ret->atime, ret->mtime, (unsigned long long)ret->length,
1245                 ret->name, ret->uid, ret->gid, ret->muid, ret->extension,
1246                 ret->n_uid, ret->n_gid, ret->n_muid);
1247
1248         p9_free_req(clnt, req);
1249         return ret;
1250
1251 error:
1252         kfree(ret);
1253         return ERR_PTR(err);
1254 }
1255 EXPORT_SYMBOL(p9_client_stat);
1256
1257 static int p9_client_statsize(struct p9_wstat *wst, int optional)
1258 {
1259         int ret;
1260
1261         /* NOTE: size shouldn't include its own length */
1262         /* size[2] type[2] dev[4] qid[13] */
1263         /* mode[4] atime[4] mtime[4] length[8]*/
1264         /* name[s] uid[s] gid[s] muid[s] */
1265         ret = 2+4+13+4+4+4+8+2+2+2+2;
1266
1267         if (wst->name)
1268                 ret += strlen(wst->name);
1269         if (wst->uid)
1270                 ret += strlen(wst->uid);
1271         if (wst->gid)
1272                 ret += strlen(wst->gid);
1273         if (wst->muid)
1274                 ret += strlen(wst->muid);
1275
1276         if (optional) {
1277                 ret += 2+4+4+4; /* extension[s] n_uid[4] n_gid[4] n_muid[4] */
1278                 if (wst->extension)
1279                         ret += strlen(wst->extension);
1280         }
1281
1282         return ret;
1283 }
1284
1285 int p9_client_wstat(struct p9_fid *fid, struct p9_wstat *wst)
1286 {
1287         int err;
1288         struct p9_req_t *req;
1289         struct p9_client *clnt;
1290
1291         err = 0;
1292         clnt = fid->clnt;
1293         wst->size = p9_client_statsize(wst, clnt->dotu);
1294         P9_DPRINTK(P9_DEBUG_9P, ">>> TWSTAT fid %d\n", fid->fid);
1295         P9_DPRINTK(P9_DEBUG_9P,
1296                 "     sz=%x type=%x dev=%x qid=%x.%llx.%x\n"
1297                 "     mode=%8.8x atime=%8.8x mtime=%8.8x length=%llx\n"
1298                 "     name=%s uid=%s gid=%s muid=%s extension=(%s)\n"
1299                 "     uid=%d gid=%d n_muid=%d\n",
1300                 wst->size, wst->type, wst->dev, wst->qid.type,
1301                 (unsigned long long)wst->qid.path, wst->qid.version, wst->mode,
1302                 wst->atime, wst->mtime, (unsigned long long)wst->length,
1303                 wst->name, wst->uid, wst->gid, wst->muid, wst->extension,
1304                 wst->n_uid, wst->n_gid, wst->n_muid);
1305
1306         req = p9_client_rpc(clnt, P9_TWSTAT, "dwS", fid->fid, wst->size+2, wst);
1307         if (IS_ERR(req)) {
1308                 err = PTR_ERR(req);
1309                 goto error;
1310         }
1311
1312         P9_DPRINTK(P9_DEBUG_9P, "<<< RWSTAT fid %d\n", fid->fid);
1313
1314         p9_free_req(clnt, req);
1315 error:
1316         return err;
1317 }
1318 EXPORT_SYMBOL(p9_client_wstat);