]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blob - net/9p/conv.c
aa2aa9884f955d37b6c7bd2c4d6923dccf2932f6
[linux-2.6-omap-h63xx.git] / net / 9p / conv.c
1 /*
2  * net/9p/conv.c
3  *
4  * 9P protocol conversion functions
5  *
6  *  Copyright (C) 2004, 2005 by Latchesar Ionkov <lucho@ionkov.net>
7  *  Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
8  *  Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
9  *
10  *  This program is free software; you can redistribute it and/or modify
11  *  it under the terms of the GNU General Public License version 2
12  *  as published by the Free Software Foundation.
13  *
14  *  This program is distributed in the hope that it will be useful,
15  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  *  GNU General Public License for more details.
18  *
19  *  You should have received a copy of the GNU General Public License
20  *  along with this program; if not, write to:
21  *  Free Software Foundation
22  *  51 Franklin Street, Fifth Floor
23  *  Boston, MA  02111-1301  USA
24  *
25  */
26
27 #include <linux/module.h>
28 #include <linux/errno.h>
29 #include <linux/fs.h>
30 #include <linux/sched.h>
31 #include <linux/idr.h>
32 #include <linux/uaccess.h>
33 #include <net/9p/9p.h>
34
35 /*
36  * Buffer to help with string parsing
37  */
38 struct cbuf {
39         unsigned char *sp;
40         unsigned char *p;
41         unsigned char *ep;
42 };
43
44 static inline void buf_init(struct cbuf *buf, void *data, int datalen)
45 {
46         buf->sp = buf->p = data;
47         buf->ep = data + datalen;
48 }
49
50 static inline int buf_check_overflow(struct cbuf *buf)
51 {
52         return buf->p > buf->ep;
53 }
54
55 static int buf_check_size(struct cbuf *buf, int len)
56 {
57         if (buf->p + len > buf->ep) {
58                 if (buf->p < buf->ep) {
59                         P9_EPRINTK(KERN_ERR,
60                                 "buffer overflow: want %d has %d\n", len,
61                                 (int)(buf->ep - buf->p));
62                         dump_stack();
63                         buf->p = buf->ep + 1;
64                 }
65
66                 return 0;
67         }
68
69         return 1;
70 }
71
72 static void *buf_alloc(struct cbuf *buf, int len)
73 {
74         void *ret = NULL;
75
76         if (buf_check_size(buf, len)) {
77                 ret = buf->p;
78                 buf->p += len;
79         }
80
81         return ret;
82 }
83
84 static void buf_put_int8(struct cbuf *buf, u8 val)
85 {
86         if (buf_check_size(buf, 1)) {
87                 buf->p[0] = val;
88                 buf->p++;
89         }
90 }
91
92 static void buf_put_int16(struct cbuf *buf, u16 val)
93 {
94         if (buf_check_size(buf, 2)) {
95                 *(__le16 *) buf->p = cpu_to_le16(val);
96                 buf->p += 2;
97         }
98 }
99
100 static void buf_put_int32(struct cbuf *buf, u32 val)
101 {
102         if (buf_check_size(buf, 4)) {
103                 *(__le32 *)buf->p = cpu_to_le32(val);
104                 buf->p += 4;
105         }
106 }
107
108 static void buf_put_int64(struct cbuf *buf, u64 val)
109 {
110         if (buf_check_size(buf, 8)) {
111                 *(__le64 *)buf->p = cpu_to_le64(val);
112                 buf->p += 8;
113         }
114 }
115
116 static char *buf_put_stringn(struct cbuf *buf, const char *s, u16 slen)
117 {
118         char *ret;
119
120         ret = NULL;
121         if (buf_check_size(buf, slen + 2)) {
122                 buf_put_int16(buf, slen);
123                 ret = buf->p;
124                 memcpy(buf->p, s, slen);
125                 buf->p += slen;
126         }
127
128         return ret;
129 }
130
131 static inline void buf_put_string(struct cbuf *buf, const char *s)
132 {
133         buf_put_stringn(buf, s, strlen(s));
134 }
135
136 static u8 buf_get_int8(struct cbuf *buf)
137 {
138         u8 ret = 0;
139
140         if (buf_check_size(buf, 1)) {
141                 ret = buf->p[0];
142                 buf->p++;
143         }
144
145         return ret;
146 }
147
148 static u16 buf_get_int16(struct cbuf *buf)
149 {
150         u16 ret = 0;
151
152         if (buf_check_size(buf, 2)) {
153                 ret = le16_to_cpu(*(__le16 *)buf->p);
154                 buf->p += 2;
155         }
156
157         return ret;
158 }
159
160 static u32 buf_get_int32(struct cbuf *buf)
161 {
162         u32 ret = 0;
163
164         if (buf_check_size(buf, 4)) {
165                 ret = le32_to_cpu(*(__le32 *)buf->p);
166                 buf->p += 4;
167         }
168
169         return ret;
170 }
171
172 static u64 buf_get_int64(struct cbuf *buf)
173 {
174         u64 ret = 0;
175
176         if (buf_check_size(buf, 8)) {
177                 ret = le64_to_cpu(*(__le64 *)buf->p);
178                 buf->p += 8;
179         }
180
181         return ret;
182 }
183
184 static void buf_get_str(struct cbuf *buf, struct p9_str *vstr)
185 {
186         vstr->len = buf_get_int16(buf);
187         if (!buf_check_overflow(buf) && buf_check_size(buf, vstr->len)) {
188                 vstr->str = buf->p;
189                 buf->p += vstr->len;
190         } else {
191                 vstr->len = 0;
192                 vstr->str = NULL;
193         }
194 }
195
196 static void buf_get_qid(struct cbuf *bufp, struct p9_qid *qid)
197 {
198         qid->type = buf_get_int8(bufp);
199         qid->version = buf_get_int32(bufp);
200         qid->path = buf_get_int64(bufp);
201 }
202
203 /**
204  * p9_size_wstat - calculate the size of a variable length stat struct
205  * @stat: metadata (stat) structure
206  * @dotu: non-zero if 9P2000.u
207  *
208  */
209
210 static int p9_size_wstat(struct p9_wstat *wstat, int dotu)
211 {
212         int size = 0;
213
214         if (wstat == NULL) {
215                 P9_EPRINTK(KERN_ERR, "p9_size_stat: got a NULL stat pointer\n");
216                 return 0;
217         }
218
219         size =                  /* 2 + *//* size[2] */
220             2 +                 /* type[2] */
221             4 +                 /* dev[4] */
222             1 +                 /* qid.type[1] */
223             4 +                 /* qid.vers[4] */
224             8 +                 /* qid.path[8] */
225             4 +                 /* mode[4] */
226             4 +                 /* atime[4] */
227             4 +                 /* mtime[4] */
228             8 +                 /* length[8] */
229             8;                  /* minimum sum of string lengths */
230
231         if (wstat->name)
232                 size += strlen(wstat->name);
233         if (wstat->uid)
234                 size += strlen(wstat->uid);
235         if (wstat->gid)
236                 size += strlen(wstat->gid);
237         if (wstat->muid)
238                 size += strlen(wstat->muid);
239
240         if (dotu) {
241                 size += 4 +     /* n_uid[4] */
242                     4 +         /* n_gid[4] */
243                     4 +         /* n_muid[4] */
244                     2;          /* string length of extension[4] */
245                 if (wstat->extension)
246                         size += strlen(wstat->extension);
247         }
248
249         return size;
250 }
251
252 /**
253  * buf_get_stat - safely decode a recieved metadata (stat) structure
254  * @bufp: buffer to deserialize
255  * @stat: metadata (stat) structure
256  * @dotu: non-zero if 9P2000.u
257  *
258  */
259
260 static void
261 buf_get_stat(struct cbuf *bufp, struct p9_stat *stat, int dotu)
262 {
263         stat->size = buf_get_int16(bufp);
264         stat->type = buf_get_int16(bufp);
265         stat->dev = buf_get_int32(bufp);
266         stat->qid.type = buf_get_int8(bufp);
267         stat->qid.version = buf_get_int32(bufp);
268         stat->qid.path = buf_get_int64(bufp);
269         stat->mode = buf_get_int32(bufp);
270         stat->atime = buf_get_int32(bufp);
271         stat->mtime = buf_get_int32(bufp);
272         stat->length = buf_get_int64(bufp);
273         buf_get_str(bufp, &stat->name);
274         buf_get_str(bufp, &stat->uid);
275         buf_get_str(bufp, &stat->gid);
276         buf_get_str(bufp, &stat->muid);
277
278         if (dotu) {
279                 buf_get_str(bufp, &stat->extension);
280                 stat->n_uid = buf_get_int32(bufp);
281                 stat->n_gid = buf_get_int32(bufp);
282                 stat->n_muid = buf_get_int32(bufp);
283         }
284 }
285
286 /**
287  * p9_deserialize_stat - decode a received metadata structure
288  * @buf: buffer to deserialize
289  * @buflen: length of received buffer
290  * @stat: metadata structure to decode into
291  * @dotu: non-zero if 9P2000.u
292  *
293  * Note: stat will point to the buf region.
294  */
295
296 int
297 p9_deserialize_stat(void *buf, u32 buflen, struct p9_stat *stat,
298                 int dotu)
299 {
300         struct cbuf buffer;
301         struct cbuf *bufp = &buffer;
302         unsigned char *p;
303
304         buf_init(bufp, buf, buflen);
305         p = bufp->p;
306         buf_get_stat(bufp, stat, dotu);
307
308         if (buf_check_overflow(bufp))
309                 return 0;
310         else
311                 return bufp->p - p;
312 }
313 EXPORT_SYMBOL(p9_deserialize_stat);
314
315 /**
316  * deserialize_fcall - unmarshal a response
317  * @buf: recieved buffer
318  * @buflen: length of received buffer
319  * @rcall: fcall structure to populate
320  * @rcalllen: length of fcall structure to populate
321  * @dotu: non-zero if 9P2000.u
322  *
323  */
324
325 int
326 p9_deserialize_fcall(void *buf, u32 buflen, struct p9_fcall *rcall,
327                        int dotu)
328 {
329
330         struct cbuf buffer;
331         struct cbuf *bufp = &buffer;
332         int i = 0;
333
334         buf_init(bufp, buf, buflen);
335
336         rcall->size = buf_get_int32(bufp);
337         rcall->id = buf_get_int8(bufp);
338         rcall->tag = buf_get_int16(bufp);
339
340         P9_DPRINTK(P9_DEBUG_CONV, "size %d id %d tag %d\n", rcall->size,
341                                                         rcall->id, rcall->tag);
342
343         switch (rcall->id) {
344         default:
345                 P9_EPRINTK(KERN_ERR, "unknown message type: %d\n", rcall->id);
346                 return -EPROTO;
347         case P9_RVERSION:
348                 rcall->params.rversion.msize = buf_get_int32(bufp);
349                 buf_get_str(bufp, &rcall->params.rversion.version);
350                 break;
351         case P9_RFLUSH:
352                 break;
353         case P9_RATTACH:
354                 rcall->params.rattach.qid.type = buf_get_int8(bufp);
355                 rcall->params.rattach.qid.version = buf_get_int32(bufp);
356                 rcall->params.rattach.qid.path = buf_get_int64(bufp);
357                 break;
358         case P9_RWALK:
359                 rcall->params.rwalk.nwqid = buf_get_int16(bufp);
360                 if (rcall->params.rwalk.nwqid > P9_MAXWELEM) {
361                         P9_EPRINTK(KERN_ERR,
362                                         "Rwalk with more than %d qids: %d\n",
363                                         P9_MAXWELEM, rcall->params.rwalk.nwqid);
364                         return -EPROTO;
365                 }
366
367                 for (i = 0; i < rcall->params.rwalk.nwqid; i++)
368                         buf_get_qid(bufp, &rcall->params.rwalk.wqids[i]);
369                 break;
370         case P9_ROPEN:
371                 buf_get_qid(bufp, &rcall->params.ropen.qid);
372                 rcall->params.ropen.iounit = buf_get_int32(bufp);
373                 break;
374         case P9_RCREATE:
375                 buf_get_qid(bufp, &rcall->params.rcreate.qid);
376                 rcall->params.rcreate.iounit = buf_get_int32(bufp);
377                 break;
378         case P9_RREAD:
379                 rcall->params.rread.count = buf_get_int32(bufp);
380                 rcall->params.rread.data = bufp->p;
381                 buf_check_size(bufp, rcall->params.rread.count);
382                 break;
383         case P9_RWRITE:
384                 rcall->params.rwrite.count = buf_get_int32(bufp);
385                 break;
386         case P9_RCLUNK:
387                 break;
388         case P9_RREMOVE:
389                 break;
390         case P9_RSTAT:
391                 buf_get_int16(bufp);
392                 buf_get_stat(bufp, &rcall->params.rstat.stat, dotu);
393                 break;
394         case P9_RWSTAT:
395                 break;
396         case P9_RERROR:
397                 buf_get_str(bufp, &rcall->params.rerror.error);
398                 if (dotu)
399                         rcall->params.rerror.errno = buf_get_int16(bufp);
400                 break;
401         }
402
403         if (buf_check_overflow(bufp)) {
404                 P9_DPRINTK(P9_DEBUG_ERROR, "buffer overflow\n");
405                 return -EIO;
406         }
407
408         return bufp->p - bufp->sp;
409 }
410 EXPORT_SYMBOL(p9_deserialize_fcall);
411
412 static inline void p9_put_int8(struct cbuf *bufp, u8 val, u8 * p)
413 {
414         *p = val;
415         buf_put_int8(bufp, val);
416 }
417
418 static inline void p9_put_int16(struct cbuf *bufp, u16 val, u16 * p)
419 {
420         *p = val;
421         buf_put_int16(bufp, val);
422 }
423
424 static inline void p9_put_int32(struct cbuf *bufp, u32 val, u32 * p)
425 {
426         *p = val;
427         buf_put_int32(bufp, val);
428 }
429
430 static inline void p9_put_int64(struct cbuf *bufp, u64 val, u64 * p)
431 {
432         *p = val;
433         buf_put_int64(bufp, val);
434 }
435
436 static void
437 p9_put_str(struct cbuf *bufp, char *data, struct p9_str *str)
438 {
439         int len;
440         char *s;
441
442         if (data)
443                 len = strlen(data);
444         else
445                 len = 0;
446
447         s = buf_put_stringn(bufp, data, len);
448         if (str) {
449                 str->len = len;
450                 str->str = s;
451         }
452 }
453
454 static int
455 p9_put_data(struct cbuf *bufp, const char *data, int count,
456                    unsigned char **pdata)
457 {
458         *pdata = buf_alloc(bufp, count);
459         memmove(*pdata, data, count);
460         return count;
461 }
462
463 static int
464 p9_put_user_data(struct cbuf *bufp, const char __user *data, int count,
465                    unsigned char **pdata)
466 {
467         *pdata = buf_alloc(bufp, count);
468         return copy_from_user(*pdata, data, count);
469 }
470
471 static void
472 p9_put_wstat(struct cbuf *bufp, struct p9_wstat *wstat,
473                struct p9_stat *stat, int statsz, int dotu)
474 {
475         p9_put_int16(bufp, statsz, &stat->size);
476         p9_put_int16(bufp, wstat->type, &stat->type);
477         p9_put_int32(bufp, wstat->dev, &stat->dev);
478         p9_put_int8(bufp, wstat->qid.type, &stat->qid.type);
479         p9_put_int32(bufp, wstat->qid.version, &stat->qid.version);
480         p9_put_int64(bufp, wstat->qid.path, &stat->qid.path);
481         p9_put_int32(bufp, wstat->mode, &stat->mode);
482         p9_put_int32(bufp, wstat->atime, &stat->atime);
483         p9_put_int32(bufp, wstat->mtime, &stat->mtime);
484         p9_put_int64(bufp, wstat->length, &stat->length);
485
486         p9_put_str(bufp, wstat->name, &stat->name);
487         p9_put_str(bufp, wstat->uid, &stat->uid);
488         p9_put_str(bufp, wstat->gid, &stat->gid);
489         p9_put_str(bufp, wstat->muid, &stat->muid);
490
491         if (dotu) {
492                 p9_put_str(bufp, wstat->extension, &stat->extension);
493                 p9_put_int32(bufp, wstat->n_uid, &stat->n_uid);
494                 p9_put_int32(bufp, wstat->n_gid, &stat->n_gid);
495                 p9_put_int32(bufp, wstat->n_muid, &stat->n_muid);
496         }
497 }
498
499 static struct p9_fcall *
500 p9_create_common(struct cbuf *bufp, u32 size, u8 id)
501 {
502         struct p9_fcall *fc;
503
504         size += 4 + 1 + 2;      /* size[4] id[1] tag[2] */
505         fc = kmalloc(sizeof(struct p9_fcall) + size, GFP_KERNEL);
506         if (!fc)
507                 return ERR_PTR(-ENOMEM);
508
509         fc->sdata = (char *)fc + sizeof(*fc);
510
511         buf_init(bufp, (char *)fc->sdata, size);
512         p9_put_int32(bufp, size, &fc->size);
513         p9_put_int8(bufp, id, &fc->id);
514         p9_put_int16(bufp, P9_NOTAG, &fc->tag);
515
516         return fc;
517 }
518
519 void p9_set_tag(struct p9_fcall *fc, u16 tag)
520 {
521         fc->tag = tag;
522         *(__le16 *) (fc->sdata + 5) = cpu_to_le16(tag);
523 }
524 EXPORT_SYMBOL(p9_set_tag);
525
526 struct p9_fcall *p9_create_tversion(u32 msize, char *version)
527 {
528         int size;
529         struct p9_fcall *fc;
530         struct cbuf buffer;
531         struct cbuf *bufp = &buffer;
532
533         size = 4 + 2 + strlen(version); /* msize[4] version[s] */
534         fc = p9_create_common(bufp, size, P9_TVERSION);
535         if (IS_ERR(fc))
536                 goto error;
537
538         p9_put_int32(bufp, msize, &fc->params.tversion.msize);
539         p9_put_str(bufp, version, &fc->params.tversion.version);
540
541         if (buf_check_overflow(bufp)) {
542                 kfree(fc);
543                 fc = ERR_PTR(-ENOMEM);
544         }
545 error:
546         return fc;
547 }
548 EXPORT_SYMBOL(p9_create_tversion);
549
550 struct p9_fcall *p9_create_tauth(u32 afid, char *uname, char *aname,
551         u32 n_uname, int dotu)
552 {
553         int size;
554         struct p9_fcall *fc;
555         struct cbuf buffer;
556         struct cbuf *bufp = &buffer;
557
558         /* afid[4] uname[s] aname[s] */
559         size = 4 + 2 + 2;
560         if (uname)
561                 size += strlen(uname);
562
563         if (aname)
564                 size += strlen(aname);
565
566         if (dotu)
567                 size += 4;      /* n_uname */
568
569         fc = p9_create_common(bufp, size, P9_TAUTH);
570         if (IS_ERR(fc))
571                 goto error;
572
573         p9_put_int32(bufp, afid, &fc->params.tauth.afid);
574         p9_put_str(bufp, uname, &fc->params.tauth.uname);
575         p9_put_str(bufp, aname, &fc->params.tauth.aname);
576         if (dotu)
577                 p9_put_int32(bufp, n_uname, &fc->params.tauth.n_uname);
578
579         if (buf_check_overflow(bufp)) {
580                 kfree(fc);
581                 fc = ERR_PTR(-ENOMEM);
582         }
583 error:
584         return fc;
585 }
586 EXPORT_SYMBOL(p9_create_tauth);
587
588 struct p9_fcall *
589 p9_create_tattach(u32 fid, u32 afid, char *uname, char *aname,
590         u32 n_uname, int dotu)
591 {
592         int size;
593         struct p9_fcall *fc;
594         struct cbuf buffer;
595         struct cbuf *bufp = &buffer;
596
597         /* fid[4] afid[4] uname[s] aname[s] */
598         size = 4 + 4 + 2 + 2;
599         if (uname)
600                 size += strlen(uname);
601
602         if (aname)
603                 size += strlen(aname);
604
605         if (dotu)
606                 size += 4;      /* n_uname */
607
608         fc = p9_create_common(bufp, size, P9_TATTACH);
609         if (IS_ERR(fc))
610                 goto error;
611
612         p9_put_int32(bufp, fid, &fc->params.tattach.fid);
613         p9_put_int32(bufp, afid, &fc->params.tattach.afid);
614         p9_put_str(bufp, uname, &fc->params.tattach.uname);
615         p9_put_str(bufp, aname, &fc->params.tattach.aname);
616         if (dotu)
617                 p9_put_int32(bufp, n_uname, &fc->params.tattach.n_uname);
618
619 error:
620         return fc;
621 }
622 EXPORT_SYMBOL(p9_create_tattach);
623
624 struct p9_fcall *p9_create_tflush(u16 oldtag)
625 {
626         int size;
627         struct p9_fcall *fc;
628         struct cbuf buffer;
629         struct cbuf *bufp = &buffer;
630
631         size = 2;               /* oldtag[2] */
632         fc = p9_create_common(bufp, size, P9_TFLUSH);
633         if (IS_ERR(fc))
634                 goto error;
635
636         p9_put_int16(bufp, oldtag, &fc->params.tflush.oldtag);
637
638         if (buf_check_overflow(bufp)) {
639                 kfree(fc);
640                 fc = ERR_PTR(-ENOMEM);
641         }
642 error:
643         return fc;
644 }
645 EXPORT_SYMBOL(p9_create_tflush);
646
647 struct p9_fcall *p9_create_twalk(u32 fid, u32 newfid, u16 nwname,
648                                      char **wnames)
649 {
650         int i, size;
651         struct p9_fcall *fc;
652         struct cbuf buffer;
653         struct cbuf *bufp = &buffer;
654
655         if (nwname > P9_MAXWELEM) {
656                 P9_DPRINTK(P9_DEBUG_ERROR, "nwname > %d\n", P9_MAXWELEM);
657                 return NULL;
658         }
659
660         size = 4 + 4 + 2;       /* fid[4] newfid[4] nwname[2] ... */
661         for (i = 0; i < nwname; i++) {
662                 size += 2 + strlen(wnames[i]);  /* wname[s] */
663         }
664
665         fc = p9_create_common(bufp, size, P9_TWALK);
666         if (IS_ERR(fc))
667                 goto error;
668
669         p9_put_int32(bufp, fid, &fc->params.twalk.fid);
670         p9_put_int32(bufp, newfid, &fc->params.twalk.newfid);
671         p9_put_int16(bufp, nwname, &fc->params.twalk.nwname);
672         for (i = 0; i < nwname; i++) {
673                 p9_put_str(bufp, wnames[i], &fc->params.twalk.wnames[i]);
674         }
675
676         if (buf_check_overflow(bufp)) {
677                 kfree(fc);
678                 fc = ERR_PTR(-ENOMEM);
679         }
680 error:
681         return fc;
682 }
683 EXPORT_SYMBOL(p9_create_twalk);
684
685 struct p9_fcall *p9_create_topen(u32 fid, u8 mode)
686 {
687         int size;
688         struct p9_fcall *fc;
689         struct cbuf buffer;
690         struct cbuf *bufp = &buffer;
691
692         size = 4 + 1;           /* fid[4] mode[1] */
693         fc = p9_create_common(bufp, size, P9_TOPEN);
694         if (IS_ERR(fc))
695                 goto error;
696
697         p9_put_int32(bufp, fid, &fc->params.topen.fid);
698         p9_put_int8(bufp, mode, &fc->params.topen.mode);
699
700         if (buf_check_overflow(bufp)) {
701                 kfree(fc);
702                 fc = ERR_PTR(-ENOMEM);
703         }
704 error:
705         return fc;
706 }
707 EXPORT_SYMBOL(p9_create_topen);
708
709 struct p9_fcall *p9_create_tcreate(u32 fid, char *name, u32 perm, u8 mode,
710         char *extension, int dotu)
711 {
712         int size;
713         struct p9_fcall *fc;
714         struct cbuf buffer;
715         struct cbuf *bufp = &buffer;
716
717         /* fid[4] name[s] perm[4] mode[1] */
718         size = 4 + 2 + strlen(name) + 4 + 1;
719         if (dotu) {
720                 size += 2 +                     /* extension[s] */
721                     (extension == NULL ? 0 : strlen(extension));
722         }
723
724         fc = p9_create_common(bufp, size, P9_TCREATE);
725         if (IS_ERR(fc))
726                 goto error;
727
728         p9_put_int32(bufp, fid, &fc->params.tcreate.fid);
729         p9_put_str(bufp, name, &fc->params.tcreate.name);
730         p9_put_int32(bufp, perm, &fc->params.tcreate.perm);
731         p9_put_int8(bufp, mode, &fc->params.tcreate.mode);
732         if (dotu)
733                 p9_put_str(bufp, extension, &fc->params.tcreate.extension);
734
735         if (buf_check_overflow(bufp)) {
736                 kfree(fc);
737                 fc = ERR_PTR(-ENOMEM);
738         }
739 error:
740         return fc;
741 }
742 EXPORT_SYMBOL(p9_create_tcreate);
743
744 struct p9_fcall *p9_create_tread(u32 fid, u64 offset, u32 count)
745 {
746         int size;
747         struct p9_fcall *fc;
748         struct cbuf buffer;
749         struct cbuf *bufp = &buffer;
750
751         size = 4 + 8 + 4;       /* fid[4] offset[8] count[4] */
752         fc = p9_create_common(bufp, size, P9_TREAD);
753         if (IS_ERR(fc))
754                 goto error;
755
756         p9_put_int32(bufp, fid, &fc->params.tread.fid);
757         p9_put_int64(bufp, offset, &fc->params.tread.offset);
758         p9_put_int32(bufp, count, &fc->params.tread.count);
759
760         if (buf_check_overflow(bufp)) {
761                 kfree(fc);
762                 fc = ERR_PTR(-ENOMEM);
763         }
764 error:
765         return fc;
766 }
767 EXPORT_SYMBOL(p9_create_tread);
768
769 struct p9_fcall *p9_create_twrite(u32 fid, u64 offset, u32 count,
770                                       const char *data)
771 {
772         int size, err;
773         struct p9_fcall *fc;
774         struct cbuf buffer;
775         struct cbuf *bufp = &buffer;
776
777         /* fid[4] offset[8] count[4] data[count] */
778         size = 4 + 8 + 4 + count;
779         fc = p9_create_common(bufp, size, P9_TWRITE);
780         if (IS_ERR(fc))
781                 goto error;
782
783         p9_put_int32(bufp, fid, &fc->params.twrite.fid);
784         p9_put_int64(bufp, offset, &fc->params.twrite.offset);
785         p9_put_int32(bufp, count, &fc->params.twrite.count);
786         err = p9_put_data(bufp, data, count, &fc->params.twrite.data);
787         if (err) {
788                 kfree(fc);
789                 fc = ERR_PTR(err);
790                 goto error;
791         }
792
793         if (buf_check_overflow(bufp)) {
794                 kfree(fc);
795                 fc = ERR_PTR(-ENOMEM);
796         }
797 error:
798         return fc;
799 }
800 EXPORT_SYMBOL(p9_create_twrite);
801
802 struct p9_fcall *p9_create_twrite_u(u32 fid, u64 offset, u32 count,
803                                       const char __user *data)
804 {
805         int size, err;
806         struct p9_fcall *fc;
807         struct cbuf buffer;
808         struct cbuf *bufp = &buffer;
809
810         /* fid[4] offset[8] count[4] data[count] */
811         size = 4 + 8 + 4 + count;
812         fc = p9_create_common(bufp, size, P9_TWRITE);
813         if (IS_ERR(fc))
814                 goto error;
815
816         p9_put_int32(bufp, fid, &fc->params.twrite.fid);
817         p9_put_int64(bufp, offset, &fc->params.twrite.offset);
818         p9_put_int32(bufp, count, &fc->params.twrite.count);
819         err = p9_put_user_data(bufp, data, count, &fc->params.twrite.data);
820         if (err) {
821                 kfree(fc);
822                 fc = ERR_PTR(err);
823                 goto error;
824         }
825
826         if (buf_check_overflow(bufp)) {
827                 kfree(fc);
828                 fc = ERR_PTR(-ENOMEM);
829         }
830 error:
831         return fc;
832 }
833 EXPORT_SYMBOL(p9_create_twrite_u);
834
835 struct p9_fcall *p9_create_tclunk(u32 fid)
836 {
837         int size;
838         struct p9_fcall *fc;
839         struct cbuf buffer;
840         struct cbuf *bufp = &buffer;
841
842         size = 4;               /* fid[4] */
843         fc = p9_create_common(bufp, size, P9_TCLUNK);
844         if (IS_ERR(fc))
845                 goto error;
846
847         p9_put_int32(bufp, fid, &fc->params.tclunk.fid);
848
849         if (buf_check_overflow(bufp)) {
850                 kfree(fc);
851                 fc = ERR_PTR(-ENOMEM);
852         }
853 error:
854         return fc;
855 }
856 EXPORT_SYMBOL(p9_create_tclunk);
857
858 struct p9_fcall *p9_create_tremove(u32 fid)
859 {
860         int size;
861         struct p9_fcall *fc;
862         struct cbuf buffer;
863         struct cbuf *bufp = &buffer;
864
865         size = 4;               /* fid[4] */
866         fc = p9_create_common(bufp, size, P9_TREMOVE);
867         if (IS_ERR(fc))
868                 goto error;
869
870         p9_put_int32(bufp, fid, &fc->params.tremove.fid);
871
872         if (buf_check_overflow(bufp)) {
873                 kfree(fc);
874                 fc = ERR_PTR(-ENOMEM);
875         }
876 error:
877         return fc;
878 }
879 EXPORT_SYMBOL(p9_create_tremove);
880
881 struct p9_fcall *p9_create_tstat(u32 fid)
882 {
883         int size;
884         struct p9_fcall *fc;
885         struct cbuf buffer;
886         struct cbuf *bufp = &buffer;
887
888         size = 4;               /* fid[4] */
889         fc = p9_create_common(bufp, size, P9_TSTAT);
890         if (IS_ERR(fc))
891                 goto error;
892
893         p9_put_int32(bufp, fid, &fc->params.tstat.fid);
894
895         if (buf_check_overflow(bufp)) {
896                 kfree(fc);
897                 fc = ERR_PTR(-ENOMEM);
898         }
899 error:
900         return fc;
901 }
902 EXPORT_SYMBOL(p9_create_tstat);
903
904 struct p9_fcall *p9_create_twstat(u32 fid, struct p9_wstat *wstat,
905                                       int dotu)
906 {
907         int size, statsz;
908         struct p9_fcall *fc;
909         struct cbuf buffer;
910         struct cbuf *bufp = &buffer;
911
912         statsz = p9_size_wstat(wstat, dotu);
913         size = 4 + 2 + 2 + statsz;      /* fid[4] stat[n] */
914         fc = p9_create_common(bufp, size, P9_TWSTAT);
915         if (IS_ERR(fc))
916                 goto error;
917
918         p9_put_int32(bufp, fid, &fc->params.twstat.fid);
919         buf_put_int16(bufp, statsz + 2);
920         p9_put_wstat(bufp, wstat, &fc->params.twstat.stat, statsz, dotu);
921
922         if (buf_check_overflow(bufp)) {
923                 kfree(fc);
924                 fc = ERR_PTR(-ENOMEM);
925         }
926 error:
927         return fc;
928 }
929 EXPORT_SYMBOL(p9_create_twstat);