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