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