sched: move the __update_rq_clock() call to scheduler_tick()
[usb.git] / net / 9p / client.c
blobcb170750337c02047ea0b1ff41dc36a028f105dc
1 /*
2 * net/9p/clnt.c
4 * 9P Client
6 * Copyright (C) 2007 by Latchesar Ionkov <lucho@ionkov.net>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2
10 * as published by the Free Software Foundation.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to:
19 * Free Software Foundation
20 * 51 Franklin Street, Fifth Floor
21 * Boston, MA 02111-1301 USA
25 #include <linux/module.h>
26 #include <linux/errno.h>
27 #include <linux/fs.h>
28 #include <linux/idr.h>
29 #include <linux/mutex.h>
30 #include <linux/sched.h>
31 #include <linux/uaccess.h>
32 #include <net/9p/9p.h>
33 #include <net/9p/transport.h>
34 #include <net/9p/conn.h>
35 #include <net/9p/client.h>
37 static struct p9_fid *p9_fid_create(struct p9_client *clnt);
38 static void p9_fid_destroy(struct p9_fid *fid);
39 static struct p9_stat *p9_clone_stat(struct p9_stat *st, int dotu);
41 struct p9_client *p9_client_create(struct p9_transport *trans, int msize,
42 int dotu)
44 int err, n;
45 struct p9_client *clnt;
46 struct p9_fcall *tc, *rc;
47 struct p9_str *version;
49 err = 0;
50 tc = NULL;
51 rc = NULL;
52 clnt = kmalloc(sizeof(struct p9_client), GFP_KERNEL);
53 if (!clnt)
54 return ERR_PTR(-ENOMEM);
56 P9_DPRINTK(P9_DEBUG_9P, "clnt %p trans %p msize %d dotu %d\n",
57 clnt, trans, msize, dotu);
58 spin_lock_init(&clnt->lock);
59 clnt->trans = trans;
60 clnt->msize = msize;
61 clnt->dotu = dotu;
62 INIT_LIST_HEAD(&clnt->fidlist);
63 clnt->fidpool = p9_idpool_create();
64 if (!clnt->fidpool) {
65 err = PTR_ERR(clnt->fidpool);
66 clnt->fidpool = NULL;
67 goto error;
70 clnt->conn = p9_conn_create(clnt->trans, clnt->msize, &clnt->dotu);
71 if (IS_ERR(clnt->conn)) {
72 err = PTR_ERR(clnt->conn);
73 clnt->conn = NULL;
74 goto error;
77 tc = p9_create_tversion(clnt->msize, clnt->dotu?"9P2000.u":"9P2000");
78 if (IS_ERR(tc)) {
79 err = PTR_ERR(tc);
80 tc = NULL;
81 goto error;
84 err = p9_conn_rpc(clnt->conn, tc, &rc);
85 if (err)
86 goto error;
88 version = &rc->params.rversion.version;
89 if (version->len == 8 && !memcmp(version->str, "9P2000.u", 8))
90 clnt->dotu = 1;
91 else if (version->len == 6 && !memcmp(version->str, "9P2000", 6))
92 clnt->dotu = 0;
93 else {
94 err = -EREMOTEIO;
95 goto error;
98 n = rc->params.rversion.msize;
99 if (n < clnt->msize)
100 clnt->msize = n;
102 kfree(tc);
103 kfree(rc);
104 return clnt;
106 error:
107 kfree(tc);
108 kfree(rc);
109 p9_client_destroy(clnt);
110 return ERR_PTR(err);
112 EXPORT_SYMBOL(p9_client_create);
114 void p9_client_destroy(struct p9_client *clnt)
116 struct p9_fid *fid, *fidptr;
118 P9_DPRINTK(P9_DEBUG_9P, "clnt %p\n", clnt);
119 if (clnt->conn) {
120 p9_conn_destroy(clnt->conn);
121 clnt->conn = NULL;
124 if (clnt->trans) {
125 clnt->trans->close(clnt->trans);
126 kfree(clnt->trans);
127 clnt->trans = NULL;
130 list_for_each_entry_safe(fid, fidptr, &clnt->fidlist, flist)
131 p9_fid_destroy(fid);
133 if (clnt->fidpool)
134 p9_idpool_destroy(clnt->fidpool);
136 kfree(clnt);
138 EXPORT_SYMBOL(p9_client_destroy);
140 void p9_client_disconnect(struct p9_client *clnt)
142 P9_DPRINTK(P9_DEBUG_9P, "clnt %p\n", clnt);
143 clnt->trans->status = Disconnected;
144 p9_conn_cancel(clnt->conn, -EIO);
146 EXPORT_SYMBOL(p9_client_disconnect);
148 struct p9_fid *p9_client_attach(struct p9_client *clnt, struct p9_fid *afid,
149 char *uname, char *aname)
151 int err;
152 struct p9_fcall *tc, *rc;
153 struct p9_fid *fid;
155 P9_DPRINTK(P9_DEBUG_9P, "clnt %p afid %d uname %s aname %s\n",
156 clnt, afid?afid->fid:-1, uname, aname);
157 err = 0;
158 tc = NULL;
159 rc = NULL;
161 fid = p9_fid_create(clnt);
162 if (IS_ERR(fid)) {
163 err = PTR_ERR(fid);
164 fid = NULL;
165 goto error;
168 tc = p9_create_tattach(fid->fid, afid?afid->fid:P9_NOFID, uname, aname);
169 if (IS_ERR(tc)) {
170 err = PTR_ERR(tc);
171 tc = NULL;
172 goto error;
175 err = p9_conn_rpc(clnt->conn, tc, &rc);
176 if (err)
177 goto error;
179 memmove(&fid->qid, &rc->params.rattach.qid, sizeof(struct p9_qid));
180 kfree(tc);
181 kfree(rc);
182 return fid;
184 error:
185 kfree(tc);
186 kfree(rc);
187 if (fid)
188 p9_fid_destroy(fid);
189 return ERR_PTR(err);
191 EXPORT_SYMBOL(p9_client_attach);
193 struct p9_fid *p9_client_auth(struct p9_client *clnt, char *uname, char *aname)
195 int err;
196 struct p9_fcall *tc, *rc;
197 struct p9_fid *fid;
199 P9_DPRINTK(P9_DEBUG_9P, "clnt %p uname %s aname %s\n", clnt, uname,
200 aname);
201 err = 0;
202 tc = NULL;
203 rc = NULL;
205 fid = p9_fid_create(clnt);
206 if (IS_ERR(fid)) {
207 err = PTR_ERR(fid);
208 fid = NULL;
209 goto error;
212 tc = p9_create_tauth(fid->fid, uname, aname);
213 if (IS_ERR(tc)) {
214 err = PTR_ERR(tc);
215 tc = NULL;
216 goto error;
219 err = p9_conn_rpc(clnt->conn, tc, &rc);
220 if (err)
221 goto error;
223 memmove(&fid->qid, &rc->params.rauth.qid, sizeof(struct p9_qid));
224 kfree(tc);
225 kfree(rc);
226 return fid;
228 error:
229 kfree(tc);
230 kfree(rc);
231 if (fid)
232 p9_fid_destroy(fid);
233 return ERR_PTR(err);
235 EXPORT_SYMBOL(p9_client_auth);
237 struct p9_fid *p9_client_walk(struct p9_fid *oldfid, int nwname, char **wnames,
238 int clone)
240 int err;
241 struct p9_fcall *tc, *rc;
242 struct p9_client *clnt;
243 struct p9_fid *fid;
245 P9_DPRINTK(P9_DEBUG_9P, "fid %d nwname %d wname[0] %s\n",
246 oldfid->fid, nwname, wnames?wnames[0]:NULL);
247 err = 0;
248 tc = NULL;
249 rc = NULL;
250 clnt = oldfid->clnt;
251 if (clone) {
252 fid = p9_fid_create(clnt);
253 if (IS_ERR(fid)) {
254 err = PTR_ERR(fid);
255 fid = NULL;
256 goto error;
259 fid->uid = oldfid->uid;
260 } else
261 fid = oldfid;
263 tc = p9_create_twalk(oldfid->fid, fid->fid, nwname, wnames);
264 if (IS_ERR(tc)) {
265 err = PTR_ERR(tc);
266 tc = NULL;
267 goto error;
270 err = p9_conn_rpc(clnt->conn, tc, &rc);
271 if (err) {
272 if (rc && rc->id == P9_RWALK)
273 goto clunk_fid;
274 else
275 goto error;
278 if (rc->params.rwalk.nwqid != nwname) {
279 err = -ENOENT;
280 goto clunk_fid;
283 if (nwname)
284 memmove(&fid->qid,
285 &rc->params.rwalk.wqids[rc->params.rwalk.nwqid - 1],
286 sizeof(struct p9_qid));
287 else
288 fid->qid = oldfid->qid;
290 kfree(tc);
291 kfree(rc);
292 return fid;
294 clunk_fid:
295 kfree(tc);
296 kfree(rc);
297 rc = NULL;
298 tc = p9_create_tclunk(fid->fid);
299 if (IS_ERR(tc)) {
300 err = PTR_ERR(tc);
301 tc = NULL;
302 goto error;
305 p9_conn_rpc(clnt->conn, tc, &rc);
307 error:
308 kfree(tc);
309 kfree(rc);
310 if (fid && (fid != oldfid))
311 p9_fid_destroy(fid);
313 return ERR_PTR(err);
315 EXPORT_SYMBOL(p9_client_walk);
317 int p9_client_open(struct p9_fid *fid, int mode)
319 int err;
320 struct p9_fcall *tc, *rc;
321 struct p9_client *clnt;
323 P9_DPRINTK(P9_DEBUG_9P, "fid %d mode %d\n", fid->fid, mode);
324 err = 0;
325 tc = NULL;
326 rc = NULL;
327 clnt = fid->clnt;
329 if (fid->mode != -1)
330 return -EINVAL;
332 tc = p9_create_topen(fid->fid, mode);
333 if (IS_ERR(tc)) {
334 err = PTR_ERR(tc);
335 tc = NULL;
336 goto done;
339 err = p9_conn_rpc(clnt->conn, tc, &rc);
340 if (err)
341 goto done;
343 fid->mode = mode;
344 fid->iounit = rc->params.ropen.iounit;
346 done:
347 kfree(tc);
348 kfree(rc);
349 return err;
351 EXPORT_SYMBOL(p9_client_open);
353 int p9_client_fcreate(struct p9_fid *fid, char *name, u32 perm, int mode,
354 char *extension)
356 int err;
357 struct p9_fcall *tc, *rc;
358 struct p9_client *clnt;
360 P9_DPRINTK(P9_DEBUG_9P, "fid %d name %s perm %d mode %d\n", fid->fid,
361 name, perm, mode);
362 err = 0;
363 tc = NULL;
364 rc = NULL;
365 clnt = fid->clnt;
367 if (fid->mode != -1)
368 return -EINVAL;
370 tc = p9_create_tcreate(fid->fid, name, perm, mode, extension,
371 clnt->dotu);
372 if (IS_ERR(tc)) {
373 err = PTR_ERR(tc);
374 tc = NULL;
375 goto done;
378 err = p9_conn_rpc(clnt->conn, tc, &rc);
379 if (err)
380 goto done;
382 fid->mode = mode;
383 fid->iounit = rc->params.ropen.iounit;
385 done:
386 kfree(tc);
387 kfree(rc);
388 return err;
390 EXPORT_SYMBOL(p9_client_fcreate);
392 int p9_client_clunk(struct p9_fid *fid)
394 int err;
395 struct p9_fcall *tc, *rc;
396 struct p9_client *clnt;
398 P9_DPRINTK(P9_DEBUG_9P, "fid %d\n", fid->fid);
399 err = 0;
400 tc = NULL;
401 rc = NULL;
402 clnt = fid->clnt;
404 tc = p9_create_tclunk(fid->fid);
405 if (IS_ERR(tc)) {
406 err = PTR_ERR(tc);
407 tc = NULL;
408 goto done;
411 err = p9_conn_rpc(clnt->conn, tc, &rc);
412 if (err)
413 goto done;
415 p9_fid_destroy(fid);
417 done:
418 kfree(tc);
419 kfree(rc);
420 return err;
422 EXPORT_SYMBOL(p9_client_clunk);
424 int p9_client_remove(struct p9_fid *fid)
426 int err;
427 struct p9_fcall *tc, *rc;
428 struct p9_client *clnt;
430 P9_DPRINTK(P9_DEBUG_9P, "fid %d\n", fid->fid);
431 err = 0;
432 tc = NULL;
433 rc = NULL;
434 clnt = fid->clnt;
436 tc = p9_create_tremove(fid->fid);
437 if (IS_ERR(tc)) {
438 err = PTR_ERR(tc);
439 tc = NULL;
440 goto done;
443 err = p9_conn_rpc(clnt->conn, tc, &rc);
444 if (err)
445 goto done;
447 p9_fid_destroy(fid);
449 done:
450 kfree(tc);
451 kfree(rc);
452 return err;
454 EXPORT_SYMBOL(p9_client_remove);
456 int p9_client_read(struct p9_fid *fid, char *data, u64 offset, u32 count)
458 int err, n, rsize, total;
459 struct p9_fcall *tc, *rc;
460 struct p9_client *clnt;
462 P9_DPRINTK(P9_DEBUG_9P, "fid %d offset %llu %d\n", fid->fid,
463 (long long unsigned) offset, count);
464 err = 0;
465 tc = NULL;
466 rc = NULL;
467 clnt = fid->clnt;
468 total = 0;
470 rsize = fid->iounit;
471 if (!rsize || rsize > clnt->msize-P9_IOHDRSZ)
472 rsize = clnt->msize - P9_IOHDRSZ;
474 do {
475 if (count < rsize)
476 rsize = count;
478 tc = p9_create_tread(fid->fid, offset, rsize);
479 if (IS_ERR(tc)) {
480 err = PTR_ERR(tc);
481 tc = NULL;
482 goto error;
485 err = p9_conn_rpc(clnt->conn, tc, &rc);
486 if (err)
487 goto error;
489 n = rc->params.rread.count;
490 if (n > count)
491 n = count;
493 memmove(data, rc->params.rread.data, n);
494 count -= n;
495 data += n;
496 offset += n;
497 total += n;
498 kfree(tc);
499 tc = NULL;
500 kfree(rc);
501 rc = NULL;
502 } while (count > 0 && n == rsize);
504 return total;
506 error:
507 kfree(tc);
508 kfree(rc);
509 return err;
511 EXPORT_SYMBOL(p9_client_read);
513 int p9_client_write(struct p9_fid *fid, char *data, u64 offset, u32 count)
515 int err, n, rsize, total;
516 struct p9_fcall *tc, *rc;
517 struct p9_client *clnt;
519 P9_DPRINTK(P9_DEBUG_9P, "fid %d offset %llu count %d\n", fid->fid,
520 (long long unsigned) offset, count);
521 err = 0;
522 tc = NULL;
523 rc = NULL;
524 clnt = fid->clnt;
525 total = 0;
527 rsize = fid->iounit;
528 if (!rsize || rsize > clnt->msize-P9_IOHDRSZ)
529 rsize = clnt->msize - P9_IOHDRSZ;
531 do {
532 if (count < rsize)
533 rsize = count;
535 tc = p9_create_twrite(fid->fid, offset, rsize, data);
536 if (IS_ERR(tc)) {
537 err = PTR_ERR(tc);
538 tc = NULL;
539 goto error;
542 err = p9_conn_rpc(clnt->conn, tc, &rc);
543 if (err)
544 goto error;
546 n = rc->params.rread.count;
547 count -= n;
548 data += n;
549 offset += n;
550 total += n;
551 kfree(tc);
552 tc = NULL;
553 kfree(rc);
554 rc = NULL;
555 } while (count > 0);
557 return total;
559 error:
560 kfree(tc);
561 kfree(rc);
562 return err;
564 EXPORT_SYMBOL(p9_client_write);
567 p9_client_uread(struct p9_fid *fid, char __user *data, u64 offset, u32 count)
569 int err, n, rsize, total;
570 struct p9_fcall *tc, *rc;
571 struct p9_client *clnt;
573 P9_DPRINTK(P9_DEBUG_9P, "fid %d offset %llu count %d\n", fid->fid,
574 (long long unsigned) offset, count);
575 err = 0;
576 tc = NULL;
577 rc = NULL;
578 clnt = fid->clnt;
579 total = 0;
581 rsize = fid->iounit;
582 if (!rsize || rsize > clnt->msize-P9_IOHDRSZ)
583 rsize = clnt->msize - P9_IOHDRSZ;
585 do {
586 if (count < rsize)
587 rsize = count;
589 tc = p9_create_tread(fid->fid, offset, rsize);
590 if (IS_ERR(tc)) {
591 err = PTR_ERR(tc);
592 tc = NULL;
593 goto error;
596 err = p9_conn_rpc(clnt->conn, tc, &rc);
597 if (err)
598 goto error;
600 n = rc->params.rread.count;
601 if (n > count)
602 n = count;
604 err = copy_to_user(data, rc->params.rread.data, n);
605 if (err) {
606 err = -EFAULT;
607 goto error;
610 count -= n;
611 data += n;
612 offset += n;
613 total += n;
614 kfree(tc);
615 tc = NULL;
616 kfree(rc);
617 rc = NULL;
618 } while (count > 0 && n == rsize);
620 return total;
622 error:
623 kfree(tc);
624 kfree(rc);
625 return err;
627 EXPORT_SYMBOL(p9_client_uread);
630 p9_client_uwrite(struct p9_fid *fid, const char __user *data, u64 offset,
631 u32 count)
633 int err, n, rsize, total;
634 struct p9_fcall *tc, *rc;
635 struct p9_client *clnt;
637 P9_DPRINTK(P9_DEBUG_9P, "fid %d offset %llu count %d\n", fid->fid,
638 (long long unsigned) offset, count);
639 err = 0;
640 tc = NULL;
641 rc = NULL;
642 clnt = fid->clnt;
643 total = 0;
645 rsize = fid->iounit;
646 if (!rsize || rsize > clnt->msize-P9_IOHDRSZ)
647 rsize = clnt->msize - P9_IOHDRSZ;
649 do {
650 if (count < rsize)
651 rsize = count;
653 tc = p9_create_twrite_u(fid->fid, offset, rsize, data);
654 if (IS_ERR(tc)) {
655 err = PTR_ERR(tc);
656 tc = NULL;
657 goto error;
660 err = p9_conn_rpc(clnt->conn, tc, &rc);
661 if (err)
662 goto error;
664 n = rc->params.rread.count;
665 count -= n;
666 data += n;
667 offset += n;
668 total += n;
669 kfree(tc);
670 tc = NULL;
671 kfree(rc);
672 rc = NULL;
673 } while (count > 0);
675 return total;
677 error:
678 kfree(tc);
679 kfree(rc);
680 return err;
682 EXPORT_SYMBOL(p9_client_uwrite);
684 int p9_client_readn(struct p9_fid *fid, char *data, u64 offset, u32 count)
686 int n, total;
688 P9_DPRINTK(P9_DEBUG_9P, "fid %d offset %llu count %d\n", fid->fid,
689 (long long unsigned) offset, count);
690 n = 0;
691 total = 0;
692 while (count) {
693 n = p9_client_read(fid, data, offset, count);
694 if (n <= 0)
695 break;
697 data += n;
698 offset += n;
699 count -= n;
700 total += n;
703 if (n < 0)
704 total = n;
706 return total;
708 EXPORT_SYMBOL(p9_client_readn);
710 struct p9_stat *p9_client_stat(struct p9_fid *fid)
712 int err;
713 struct p9_fcall *tc, *rc;
714 struct p9_client *clnt;
715 struct p9_stat *ret;
717 P9_DPRINTK(P9_DEBUG_9P, "fid %d\n", fid->fid);
718 err = 0;
719 tc = NULL;
720 rc = NULL;
721 ret = NULL;
722 clnt = fid->clnt;
724 tc = p9_create_tstat(fid->fid);
725 if (IS_ERR(tc)) {
726 err = PTR_ERR(tc);
727 tc = NULL;
728 goto error;
731 err = p9_conn_rpc(clnt->conn, tc, &rc);
732 if (err)
733 goto error;
735 ret = p9_clone_stat(&rc->params.rstat.stat, clnt->dotu);
736 if (IS_ERR(ret)) {
737 err = PTR_ERR(ret);
738 ret = NULL;
739 goto error;
742 kfree(tc);
743 kfree(rc);
744 return ret;
746 error:
747 kfree(tc);
748 kfree(rc);
749 kfree(ret);
750 return ERR_PTR(err);
752 EXPORT_SYMBOL(p9_client_stat);
754 int p9_client_wstat(struct p9_fid *fid, struct p9_wstat *wst)
756 int err;
757 struct p9_fcall *tc, *rc;
758 struct p9_client *clnt;
760 P9_DPRINTK(P9_DEBUG_9P, "fid %d\n", fid->fid);
761 err = 0;
762 tc = NULL;
763 rc = NULL;
764 clnt = fid->clnt;
766 tc = p9_create_twstat(fid->fid, wst, clnt->dotu);
767 if (IS_ERR(tc)) {
768 err = PTR_ERR(tc);
769 tc = NULL;
770 goto done;
773 err = p9_conn_rpc(clnt->conn, tc, &rc);
775 done:
776 kfree(tc);
777 kfree(rc);
778 return err;
780 EXPORT_SYMBOL(p9_client_wstat);
782 struct p9_stat *p9_client_dirread(struct p9_fid *fid, u64 offset)
784 int err, n, m;
785 struct p9_fcall *tc, *rc;
786 struct p9_client *clnt;
787 struct p9_stat st, *ret;
789 P9_DPRINTK(P9_DEBUG_9P, "fid %d offset %llu\n", fid->fid,
790 (long long unsigned) offset);
791 err = 0;
792 tc = NULL;
793 rc = NULL;
794 ret = NULL;
795 clnt = fid->clnt;
797 /* if the offset is below or above the current response, free it */
798 if (offset < fid->rdir_fpos || (fid->rdir_fcall &&
799 offset >= fid->rdir_fpos+fid->rdir_fcall->params.rread.count)) {
800 fid->rdir_pos = 0;
801 if (fid->rdir_fcall)
802 fid->rdir_fpos += fid->rdir_fcall->params.rread.count;
804 kfree(fid->rdir_fcall);
805 fid->rdir_fcall = NULL;
806 if (offset < fid->rdir_fpos)
807 fid->rdir_fpos = 0;
810 if (!fid->rdir_fcall) {
811 n = fid->iounit;
812 if (!n || n > clnt->msize-P9_IOHDRSZ)
813 n = clnt->msize - P9_IOHDRSZ;
815 while (1) {
816 if (fid->rdir_fcall) {
817 fid->rdir_fpos +=
818 fid->rdir_fcall->params.rread.count;
819 kfree(fid->rdir_fcall);
820 fid->rdir_fcall = NULL;
823 tc = p9_create_tread(fid->fid, fid->rdir_fpos, n);
824 if (IS_ERR(tc)) {
825 err = PTR_ERR(tc);
826 tc = NULL;
827 goto error;
830 err = p9_conn_rpc(clnt->conn, tc, &rc);
831 if (err)
832 goto error;
834 n = rc->params.rread.count;
835 if (n == 0)
836 goto done;
838 fid->rdir_fcall = rc;
839 rc = NULL;
840 if (offset >= fid->rdir_fpos &&
841 offset < fid->rdir_fpos+n)
842 break;
845 fid->rdir_pos = 0;
848 m = offset - fid->rdir_fpos;
849 if (m < 0)
850 goto done;
852 n = p9_deserialize_stat(fid->rdir_fcall->params.rread.data + m,
853 fid->rdir_fcall->params.rread.count - m, &st, clnt->dotu);
855 if (!n) {
856 err = -EIO;
857 goto error;
860 fid->rdir_pos += n;
861 st.size = n;
862 ret = p9_clone_stat(&st, clnt->dotu);
863 if (IS_ERR(ret)) {
864 err = PTR_ERR(ret);
865 ret = NULL;
866 goto error;
869 done:
870 kfree(tc);
871 kfree(rc);
872 return ret;
874 error:
875 kfree(tc);
876 kfree(rc);
877 kfree(ret);
878 return ERR_PTR(err);
880 EXPORT_SYMBOL(p9_client_dirread);
882 static struct p9_stat *p9_clone_stat(struct p9_stat *st, int dotu)
884 int n;
885 char *p;
886 struct p9_stat *ret;
888 n = sizeof(struct p9_stat) + st->name.len + st->uid.len + st->gid.len +
889 st->muid.len;
891 if (dotu)
892 n += st->extension.len;
894 ret = kmalloc(n, GFP_KERNEL);
895 if (!ret)
896 return ERR_PTR(-ENOMEM);
898 memmove(ret, st, sizeof(struct p9_stat));
899 p = ((char *) ret) + sizeof(struct p9_stat);
900 memmove(p, st->name.str, st->name.len);
901 p += st->name.len;
902 memmove(p, st->uid.str, st->uid.len);
903 p += st->uid.len;
904 memmove(p, st->gid.str, st->gid.len);
905 p += st->gid.len;
906 memmove(p, st->muid.str, st->muid.len);
907 p += st->muid.len;
909 if (dotu) {
910 memmove(p, st->extension.str, st->extension.len);
911 p += st->extension.len;
914 return ret;
917 static struct p9_fid *p9_fid_create(struct p9_client *clnt)
919 int err;
920 struct p9_fid *fid;
922 P9_DPRINTK(P9_DEBUG_9P, "clnt %p\n", clnt);
923 fid = kmalloc(sizeof(struct p9_fid), GFP_KERNEL);
924 if (!fid)
925 return ERR_PTR(-ENOMEM);
927 fid->fid = p9_idpool_get(clnt->fidpool);
928 if (fid->fid < 0) {
929 err = -ENOSPC;
930 goto error;
933 memset(&fid->qid, 0, sizeof(struct p9_qid));
934 fid->mode = -1;
935 fid->rdir_fpos = 0;
936 fid->rdir_pos = 0;
937 fid->rdir_fcall = NULL;
938 fid->uid = current->fsuid;
939 fid->clnt = clnt;
940 fid->aux = NULL;
942 spin_lock(&clnt->lock);
943 list_add(&fid->flist, &clnt->fidlist);
944 spin_unlock(&clnt->lock);
946 return fid;
948 error:
949 kfree(fid);
950 return ERR_PTR(err);
953 static void p9_fid_destroy(struct p9_fid *fid)
955 struct p9_client *clnt;
957 P9_DPRINTK(P9_DEBUG_9P, "fid %d\n", fid->fid);
958 clnt = fid->clnt;
959 p9_idpool_put(fid->fid, clnt->fidpool);
960 spin_lock(&clnt->lock);
961 list_del(&fid->flist);
962 spin_unlock(&clnt->lock);
963 kfree(fid->rdir_fcall);
964 kfree(fid);