Merge branch 'splice' of git://brick.kernel.dk/data/git/linux-2.6-block
[linux-2.6] / fs / 9p / conv.c
1 /*
2  * linux/fs/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/idr.h>
31 #include <asm/uaccess.h>
32 #include "debug.h"
33 #include "v9fs.h"
34 #include "9p.h"
35 #include "conv.h"
36
37 /*
38  * Buffer to help with string parsing
39  */
40 struct cbuf {
41         unsigned char *sp;
42         unsigned char *p;
43         unsigned char *ep;
44 };
45
46 static inline void buf_init(struct cbuf *buf, void *data, int datalen)
47 {
48         buf->sp = buf->p = data;
49         buf->ep = data + datalen;
50 }
51
52 static inline int buf_check_overflow(struct cbuf *buf)
53 {
54         return buf->p > buf->ep;
55 }
56
57 static int buf_check_size(struct cbuf *buf, int len)
58 {
59         if (buf->p + len > buf->ep) {
60                 if (buf->p < buf->ep) {
61                         eprintk(KERN_ERR, "buffer overflow: want %d has %d\n",
62                                 len, (int)(buf->ep - buf->p));
63                         dump_stack();
64                         buf->p = buf->ep + 1;
65                 }
66
67                 return 0;
68         }
69
70         return 1;
71 }
72
73 static void *buf_alloc(struct cbuf *buf, int len)
74 {
75         void *ret = NULL;
76
77         if (buf_check_size(buf, len)) {
78                 ret = buf->p;
79                 buf->p += len;
80         }
81
82         return ret;
83 }
84
85 static void buf_put_int8(struct cbuf *buf, u8 val)
86 {
87         if (buf_check_size(buf, 1)) {
88                 buf->p[0] = val;
89                 buf->p++;
90         }
91 }
92
93 static void buf_put_int16(struct cbuf *buf, u16 val)
94 {
95         if (buf_check_size(buf, 2)) {
96                 *(__le16 *) buf->p = cpu_to_le16(val);
97                 buf->p += 2;
98         }
99 }
100
101 static void buf_put_int32(struct cbuf *buf, u32 val)
102 {
103         if (buf_check_size(buf, 4)) {
104                 *(__le32 *)buf->p = cpu_to_le32(val);
105                 buf->p += 4;
106         }
107 }
108
109 static void buf_put_int64(struct cbuf *buf, u64 val)
110 {
111         if (buf_check_size(buf, 8)) {
112                 *(__le64 *)buf->p = cpu_to_le64(val);
113                 buf->p += 8;
114         }
115 }
116
117 static char *buf_put_stringn(struct cbuf *buf, const char *s, u16 slen)
118 {
119         char *ret;
120
121         ret = NULL;
122         if (buf_check_size(buf, slen + 2)) {
123                 buf_put_int16(buf, slen);
124                 ret = buf->p;
125                 memcpy(buf->p, s, slen);
126                 buf->p += slen;
127         }
128
129         return ret;
130 }
131
132 static inline void buf_put_string(struct cbuf *buf, const char *s)
133 {
134         buf_put_stringn(buf, s, strlen(s));
135 }
136
137 static u8 buf_get_int8(struct cbuf *buf)
138 {
139         u8 ret = 0;
140
141         if (buf_check_size(buf, 1)) {
142                 ret = buf->p[0];
143                 buf->p++;
144         }
145
146         return ret;
147 }
148
149 static u16 buf_get_int16(struct cbuf *buf)
150 {
151         u16 ret = 0;
152
153         if (buf_check_size(buf, 2)) {
154                 ret = le16_to_cpu(*(__le16 *)buf->p);
155                 buf->p += 2;
156         }
157
158         return ret;
159 }
160
161 static u32 buf_get_int32(struct cbuf *buf)
162 {
163         u32 ret = 0;
164
165         if (buf_check_size(buf, 4)) {
166                 ret = le32_to_cpu(*(__le32 *)buf->p);
167                 buf->p += 4;
168         }
169
170         return ret;
171 }
172
173 static u64 buf_get_int64(struct cbuf *buf)
174 {
175         u64 ret = 0;
176
177         if (buf_check_size(buf, 8)) {
178                 ret = le64_to_cpu(*(__le64 *)buf->p);
179                 buf->p += 8;
180         }
181
182         return ret;
183 }
184
185 static void buf_get_str(struct cbuf *buf, struct v9fs_str *vstr)
186 {
187         vstr->len = buf_get_int16(buf);
188         if (!buf_check_overflow(buf) && buf_check_size(buf, vstr->len)) {
189                 vstr->str = buf->p;
190                 buf->p += vstr->len;
191         } else {
192                 vstr->len = 0;
193                 vstr->str = NULL;
194         }
195 }
196
197 static void buf_get_qid(struct cbuf *bufp, struct v9fs_qid *qid)
198 {
199         qid->type = buf_get_int8(bufp);
200         qid->version = buf_get_int32(bufp);
201         qid->path = buf_get_int64(bufp);
202 }
203
204 /**
205  * v9fs_size_wstat - calculate the size of a variable length stat struct
206  * @stat: metadata (stat) structure
207  * @extended: non-zero if 9P2000.u
208  *
209  */
210
211 static int v9fs_size_wstat(struct v9fs_wstat *wstat, int extended)
212 {
213         int size = 0;
214
215         if (wstat == NULL) {
216                 eprintk(KERN_ERR, "v9fs_size_stat: got a NULL stat pointer\n");
217                 return 0;
218         }
219
220         size =                  /* 2 + *//* size[2] */
221             2 +                 /* type[2] */
222             4 +                 /* dev[4] */
223             1 +                 /* qid.type[1] */
224             4 +                 /* qid.vers[4] */
225             8 +                 /* qid.path[8] */
226             4 +                 /* mode[4] */
227             4 +                 /* atime[4] */
228             4 +                 /* mtime[4] */
229             8 +                 /* length[8] */
230             8;                  /* minimum sum of string lengths */
231
232         if (wstat->name)
233                 size += strlen(wstat->name);
234         if (wstat->uid)
235                 size += strlen(wstat->uid);
236         if (wstat->gid)
237                 size += strlen(wstat->gid);
238         if (wstat->muid)
239                 size += strlen(wstat->muid);
240
241         if (extended) {
242                 size += 4 +     /* n_uid[4] */
243                     4 +         /* n_gid[4] */
244                     4 +         /* n_muid[4] */
245                     2;          /* string length of extension[4] */
246                 if (wstat->extension)
247                         size += strlen(wstat->extension);
248         }
249
250         return size;
251 }
252
253 /**
254  * buf_get_stat - safely decode a recieved metadata (stat) structure
255  * @bufp: buffer to deserialize
256  * @stat: metadata (stat) structure
257  * @extended: non-zero if 9P2000.u
258  *
259  */
260
261 static void
262 buf_get_stat(struct cbuf *bufp, struct v9fs_stat *stat, int extended)
263 {
264         stat->size = buf_get_int16(bufp);
265         stat->type = buf_get_int16(bufp);
266         stat->dev = buf_get_int32(bufp);
267         stat->qid.type = buf_get_int8(bufp);
268         stat->qid.version = buf_get_int32(bufp);
269         stat->qid.path = buf_get_int64(bufp);
270         stat->mode = buf_get_int32(bufp);
271         stat->atime = buf_get_int32(bufp);
272         stat->mtime = buf_get_int32(bufp);
273         stat->length = buf_get_int64(bufp);
274         buf_get_str(bufp, &stat->name);
275         buf_get_str(bufp, &stat->uid);
276         buf_get_str(bufp, &stat->gid);
277         buf_get_str(bufp, &stat->muid);
278
279         if (extended) {
280                 buf_get_str(bufp, &stat->extension);
281                 stat->n_uid = buf_get_int32(bufp);
282                 stat->n_gid = buf_get_int32(bufp);
283                 stat->n_muid = buf_get_int32(bufp);
284         }
285 }
286
287 /**
288  * v9fs_deserialize_stat - decode a received metadata structure
289  * @buf: buffer to deserialize
290  * @buflen: length of received buffer
291  * @stat: metadata structure to decode into
292  * @extended: non-zero if 9P2000.u
293  *
294  * Note: stat will point to the buf region.
295  */
296
297 int
298 v9fs_deserialize_stat(void *buf, u32 buflen, struct v9fs_stat *stat,
299                 int extended)
300 {
301         struct cbuf buffer;
302         struct cbuf *bufp = &buffer;
303         unsigned char *p;
304
305         buf_init(bufp, buf, buflen);
306         p = bufp->p;
307         buf_get_stat(bufp, stat, extended);
308
309         if (buf_check_overflow(bufp))
310                 return 0;
311         else
312                 return bufp->p - p;
313 }
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  * @extended: non-zero if 9P2000.u
322  *
323  */
324
325 int
326 v9fs_deserialize_fcall(void *buf, u32 buflen, struct v9fs_fcall *rcall,
327                        int extended)
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         dprintk(DEBUG_CONV, "size %d id %d tag %d\n", rcall->size, rcall->id,
341                 rcall->tag);
342
343         switch (rcall->id) {
344         default:
345                 eprintk(KERN_ERR, "unknown message type: %d\n", rcall->id);
346                 return -EPROTO;
347         case RVERSION:
348                 rcall->params.rversion.msize = buf_get_int32(bufp);
349                 buf_get_str(bufp, &rcall->params.rversion.version);
350                 break;
351         case RFLUSH:
352                 break;
353         case 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 RWALK:
359                 rcall->params.rwalk.nwqid = buf_get_int16(bufp);
360                 if (rcall->params.rwalk.nwqid > V9FS_MAXWELEM) {
361                         eprintk(KERN_ERR, "Rwalk with more than %d qids: %d\n",
362                                 V9FS_MAXWELEM, rcall->params.rwalk.nwqid);
363                         return -EPROTO;
364                 }
365
366                 for (i = 0; i < rcall->params.rwalk.nwqid; i++)
367                         buf_get_qid(bufp, &rcall->params.rwalk.wqids[i]);
368                 break;
369         case ROPEN:
370                 buf_get_qid(bufp, &rcall->params.ropen.qid);
371                 rcall->params.ropen.iounit = buf_get_int32(bufp);
372                 break;
373         case RCREATE:
374                 buf_get_qid(bufp, &rcall->params.rcreate.qid);
375                 rcall->params.rcreate.iounit = buf_get_int32(bufp);
376                 break;
377         case RREAD:
378                 rcall->params.rread.count = buf_get_int32(bufp);
379                 rcall->params.rread.data = bufp->p;
380                 buf_check_size(bufp, rcall->params.rread.count);
381                 break;
382         case RWRITE:
383                 rcall->params.rwrite.count = buf_get_int32(bufp);
384                 break;
385         case RCLUNK:
386                 break;
387         case RREMOVE:
388                 break;
389         case RSTAT:
390                 buf_get_int16(bufp);
391                 buf_get_stat(bufp, &rcall->params.rstat.stat, extended);
392                 break;
393         case RWSTAT:
394                 break;
395         case RERROR:
396                 buf_get_str(bufp, &rcall->params.rerror.error);
397                 if (extended)
398                         rcall->params.rerror.errno = buf_get_int16(bufp);
399                 break;
400         }
401
402         if (buf_check_overflow(bufp)) {
403                 dprintk(DEBUG_ERROR, "buffer overflow\n");
404                 return -EIO;
405         }
406
407         return bufp->p - bufp->sp;
408 }
409
410 static inline void v9fs_put_int8(struct cbuf *bufp, u8 val, u8 * p)
411 {
412         *p = val;
413         buf_put_int8(bufp, val);
414 }
415
416 static inline void v9fs_put_int16(struct cbuf *bufp, u16 val, u16 * p)
417 {
418         *p = val;
419         buf_put_int16(bufp, val);
420 }
421
422 static inline void v9fs_put_int32(struct cbuf *bufp, u32 val, u32 * p)
423 {
424         *p = val;
425         buf_put_int32(bufp, val);
426 }
427
428 static inline void v9fs_put_int64(struct cbuf *bufp, u64 val, u64 * p)
429 {
430         *p = val;
431         buf_put_int64(bufp, val);
432 }
433
434 static void
435 v9fs_put_str(struct cbuf *bufp, char *data, struct v9fs_str *str)
436 {
437         int len;
438         char *s;
439
440         if (data)
441                 len = strlen(data);
442         else
443                 len = 0;
444
445         s = buf_put_stringn(bufp, data, len);
446         if (str) {
447                 str->len = len;
448                 str->str = s;
449         }
450 }
451
452 static int
453 v9fs_put_user_data(struct cbuf *bufp, const char __user * data, int count,
454                    unsigned char **pdata)
455 {
456         *pdata = buf_alloc(bufp, count);
457         return copy_from_user(*pdata, data, count);
458 }
459
460 static void
461 v9fs_put_wstat(struct cbuf *bufp, struct v9fs_wstat *wstat,
462                struct v9fs_stat *stat, int statsz, int extended)
463 {
464         v9fs_put_int16(bufp, statsz, &stat->size);
465         v9fs_put_int16(bufp, wstat->type, &stat->type);
466         v9fs_put_int32(bufp, wstat->dev, &stat->dev);
467         v9fs_put_int8(bufp, wstat->qid.type, &stat->qid.type);
468         v9fs_put_int32(bufp, wstat->qid.version, &stat->qid.version);
469         v9fs_put_int64(bufp, wstat->qid.path, &stat->qid.path);
470         v9fs_put_int32(bufp, wstat->mode, &stat->mode);
471         v9fs_put_int32(bufp, wstat->atime, &stat->atime);
472         v9fs_put_int32(bufp, wstat->mtime, &stat->mtime);
473         v9fs_put_int64(bufp, wstat->length, &stat->length);
474
475         v9fs_put_str(bufp, wstat->name, &stat->name);
476         v9fs_put_str(bufp, wstat->uid, &stat->uid);
477         v9fs_put_str(bufp, wstat->gid, &stat->gid);
478         v9fs_put_str(bufp, wstat->muid, &stat->muid);
479
480         if (extended) {
481                 v9fs_put_str(bufp, wstat->extension, &stat->extension);
482                 v9fs_put_int32(bufp, wstat->n_uid, &stat->n_uid);
483                 v9fs_put_int32(bufp, wstat->n_gid, &stat->n_gid);
484                 v9fs_put_int32(bufp, wstat->n_muid, &stat->n_muid);
485         }
486 }
487
488 static struct v9fs_fcall *
489 v9fs_create_common(struct cbuf *bufp, u32 size, u8 id)
490 {
491         struct v9fs_fcall *fc;
492
493         size += 4 + 1 + 2;      /* size[4] id[1] tag[2] */
494         fc = kmalloc(sizeof(struct v9fs_fcall) + size, GFP_KERNEL);
495         if (!fc)
496                 return ERR_PTR(-ENOMEM);
497
498         fc->sdata = (char *)fc + sizeof(*fc);
499
500         buf_init(bufp, (char *)fc->sdata, size);
501         v9fs_put_int32(bufp, size, &fc->size);
502         v9fs_put_int8(bufp, id, &fc->id);
503         v9fs_put_int16(bufp, V9FS_NOTAG, &fc->tag);
504
505         return fc;
506 }
507
508 void v9fs_set_tag(struct v9fs_fcall *fc, u16 tag)
509 {
510         fc->tag = tag;
511         *(__le16 *) (fc->sdata + 5) = cpu_to_le16(tag);
512 }
513
514 struct v9fs_fcall *v9fs_create_tversion(u32 msize, char *version)
515 {
516         int size;
517         struct v9fs_fcall *fc;
518         struct cbuf buffer;
519         struct cbuf *bufp = &buffer;
520
521         size = 4 + 2 + strlen(version); /* msize[4] version[s] */
522         fc = v9fs_create_common(bufp, size, TVERSION);
523         if (IS_ERR(fc))
524                 goto error;
525
526         v9fs_put_int32(bufp, msize, &fc->params.tversion.msize);
527         v9fs_put_str(bufp, version, &fc->params.tversion.version);
528
529         if (buf_check_overflow(bufp)) {
530                 kfree(fc);
531                 fc = ERR_PTR(-ENOMEM);
532         }
533       error:
534         return fc;
535 }
536
537 #if 0
538 struct v9fs_fcall *v9fs_create_tauth(u32 afid, char *uname, char *aname)
539 {
540         int size;
541         struct v9fs_fcall *fc;
542         struct cbuf buffer;
543         struct cbuf *bufp = &buffer;
544
545         size = 4 + 2 + strlen(uname) + 2 + strlen(aname);       /* afid[4] uname[s] aname[s] */
546         fc = v9fs_create_common(bufp, size, TAUTH);
547         if (IS_ERR(fc))
548                 goto error;
549
550         v9fs_put_int32(bufp, afid, &fc->params.tauth.afid);
551         v9fs_put_str(bufp, uname, &fc->params.tauth.uname);
552         v9fs_put_str(bufp, aname, &fc->params.tauth.aname);
553
554         if (buf_check_overflow(bufp)) {
555                 kfree(fc);
556                 fc = ERR_PTR(-ENOMEM);
557         }
558       error:
559         return fc;
560 }
561 #endif  /*  0  */
562
563 struct v9fs_fcall *
564 v9fs_create_tattach(u32 fid, u32 afid, char *uname, char *aname)
565 {
566         int size;
567         struct v9fs_fcall *fc;
568         struct cbuf buffer;
569         struct cbuf *bufp = &buffer;
570
571         size = 4 + 4 + 2 + strlen(uname) + 2 + strlen(aname);   /* fid[4] afid[4] uname[s] aname[s] */
572         fc = v9fs_create_common(bufp, size, TATTACH);
573         if (IS_ERR(fc))
574                 goto error;
575
576         v9fs_put_int32(bufp, fid, &fc->params.tattach.fid);
577         v9fs_put_int32(bufp, afid, &fc->params.tattach.afid);
578         v9fs_put_str(bufp, uname, &fc->params.tattach.uname);
579         v9fs_put_str(bufp, aname, &fc->params.tattach.aname);
580
581       error:
582         return fc;
583 }
584
585 struct v9fs_fcall *v9fs_create_tflush(u16 oldtag)
586 {
587         int size;
588         struct v9fs_fcall *fc;
589         struct cbuf buffer;
590         struct cbuf *bufp = &buffer;
591
592         size = 2;               /* oldtag[2] */
593         fc = v9fs_create_common(bufp, size, TFLUSH);
594         if (IS_ERR(fc))
595                 goto error;
596
597         v9fs_put_int16(bufp, oldtag, &fc->params.tflush.oldtag);
598
599         if (buf_check_overflow(bufp)) {
600                 kfree(fc);
601                 fc = ERR_PTR(-ENOMEM);
602         }
603       error:
604         return fc;
605 }
606
607 struct v9fs_fcall *v9fs_create_twalk(u32 fid, u32 newfid, u16 nwname,
608                                      char **wnames)
609 {
610         int i, size;
611         struct v9fs_fcall *fc;
612         struct cbuf buffer;
613         struct cbuf *bufp = &buffer;
614
615         if (nwname > V9FS_MAXWELEM) {
616                 dprintk(DEBUG_ERROR, "nwname > %d\n", V9FS_MAXWELEM);
617                 return NULL;
618         }
619
620         size = 4 + 4 + 2;       /* fid[4] newfid[4] nwname[2] ... */
621         for (i = 0; i < nwname; i++) {
622                 size += 2 + strlen(wnames[i]);  /* wname[s] */
623         }
624
625         fc = v9fs_create_common(bufp, size, TWALK);
626         if (IS_ERR(fc))
627                 goto error;
628
629         v9fs_put_int32(bufp, fid, &fc->params.twalk.fid);
630         v9fs_put_int32(bufp, newfid, &fc->params.twalk.newfid);
631         v9fs_put_int16(bufp, nwname, &fc->params.twalk.nwname);
632         for (i = 0; i < nwname; i++) {
633                 v9fs_put_str(bufp, wnames[i], &fc->params.twalk.wnames[i]);
634         }
635
636         if (buf_check_overflow(bufp)) {
637                 kfree(fc);
638                 fc = ERR_PTR(-ENOMEM);
639         }
640       error:
641         return fc;
642 }
643
644 struct v9fs_fcall *v9fs_create_topen(u32 fid, u8 mode)
645 {
646         int size;
647         struct v9fs_fcall *fc;
648         struct cbuf buffer;
649         struct cbuf *bufp = &buffer;
650
651         size = 4 + 1;           /* fid[4] mode[1] */
652         fc = v9fs_create_common(bufp, size, TOPEN);
653         if (IS_ERR(fc))
654                 goto error;
655
656         v9fs_put_int32(bufp, fid, &fc->params.topen.fid);
657         v9fs_put_int8(bufp, mode, &fc->params.topen.mode);
658
659         if (buf_check_overflow(bufp)) {
660                 kfree(fc);
661                 fc = ERR_PTR(-ENOMEM);
662         }
663       error:
664         return fc;
665 }
666
667 struct v9fs_fcall *v9fs_create_tcreate(u32 fid, char *name, u32 perm, u8 mode,
668         char *extension, int extended)
669 {
670         int size;
671         struct v9fs_fcall *fc;
672         struct cbuf buffer;
673         struct cbuf *bufp = &buffer;
674
675         size = 4 + 2 + strlen(name) + 4 + 1;    /* fid[4] name[s] perm[4] mode[1] */
676         if (extended && extension!=NULL)
677                 size += 2 + strlen(extension);  /* extension[s] */
678
679         fc = v9fs_create_common(bufp, size, TCREATE);
680         if (IS_ERR(fc))
681                 goto error;
682
683         v9fs_put_int32(bufp, fid, &fc->params.tcreate.fid);
684         v9fs_put_str(bufp, name, &fc->params.tcreate.name);
685         v9fs_put_int32(bufp, perm, &fc->params.tcreate.perm);
686         v9fs_put_int8(bufp, mode, &fc->params.tcreate.mode);
687         if (extended)
688                 v9fs_put_str(bufp, extension, &fc->params.tcreate.extension);
689
690         if (buf_check_overflow(bufp)) {
691                 kfree(fc);
692                 fc = ERR_PTR(-ENOMEM);
693         }
694       error:
695         return fc;
696 }
697
698 struct v9fs_fcall *v9fs_create_tread(u32 fid, u64 offset, u32 count)
699 {
700         int size;
701         struct v9fs_fcall *fc;
702         struct cbuf buffer;
703         struct cbuf *bufp = &buffer;
704
705         size = 4 + 8 + 4;       /* fid[4] offset[8] count[4] */
706         fc = v9fs_create_common(bufp, size, TREAD);
707         if (IS_ERR(fc))
708                 goto error;
709
710         v9fs_put_int32(bufp, fid, &fc->params.tread.fid);
711         v9fs_put_int64(bufp, offset, &fc->params.tread.offset);
712         v9fs_put_int32(bufp, count, &fc->params.tread.count);
713
714         if (buf_check_overflow(bufp)) {
715                 kfree(fc);
716                 fc = ERR_PTR(-ENOMEM);
717         }
718       error:
719         return fc;
720 }
721
722 struct v9fs_fcall *v9fs_create_twrite(u32 fid, u64 offset, u32 count,
723                                       const char __user * data)
724 {
725         int size, err;
726         struct v9fs_fcall *fc;
727         struct cbuf buffer;
728         struct cbuf *bufp = &buffer;
729
730         size = 4 + 8 + 4 + count;       /* fid[4] offset[8] count[4] data[count] */
731         fc = v9fs_create_common(bufp, size, TWRITE);
732         if (IS_ERR(fc))
733                 goto error;
734
735         v9fs_put_int32(bufp, fid, &fc->params.twrite.fid);
736         v9fs_put_int64(bufp, offset, &fc->params.twrite.offset);
737         v9fs_put_int32(bufp, count, &fc->params.twrite.count);
738         err = v9fs_put_user_data(bufp, data, count, &fc->params.twrite.data);
739         if (err) {
740                 kfree(fc);
741                 fc = ERR_PTR(err);
742         }
743
744         if (buf_check_overflow(bufp)) {
745                 kfree(fc);
746                 fc = ERR_PTR(-ENOMEM);
747         }
748       error:
749         return fc;
750 }
751
752 struct v9fs_fcall *v9fs_create_tclunk(u32 fid)
753 {
754         int size;
755         struct v9fs_fcall *fc;
756         struct cbuf buffer;
757         struct cbuf *bufp = &buffer;
758
759         size = 4;               /* fid[4] */
760         fc = v9fs_create_common(bufp, size, TCLUNK);
761         if (IS_ERR(fc))
762                 goto error;
763
764         v9fs_put_int32(bufp, fid, &fc->params.tclunk.fid);
765
766         if (buf_check_overflow(bufp)) {
767                 kfree(fc);
768                 fc = ERR_PTR(-ENOMEM);
769         }
770       error:
771         return fc;
772 }
773
774 struct v9fs_fcall *v9fs_create_tremove(u32 fid)
775 {
776         int size;
777         struct v9fs_fcall *fc;
778         struct cbuf buffer;
779         struct cbuf *bufp = &buffer;
780
781         size = 4;               /* fid[4] */
782         fc = v9fs_create_common(bufp, size, TREMOVE);
783         if (IS_ERR(fc))
784                 goto error;
785
786         v9fs_put_int32(bufp, fid, &fc->params.tremove.fid);
787
788         if (buf_check_overflow(bufp)) {
789                 kfree(fc);
790                 fc = ERR_PTR(-ENOMEM);
791         }
792       error:
793         return fc;
794 }
795
796 struct v9fs_fcall *v9fs_create_tstat(u32 fid)
797 {
798         int size;
799         struct v9fs_fcall *fc;
800         struct cbuf buffer;
801         struct cbuf *bufp = &buffer;
802
803         size = 4;               /* fid[4] */
804         fc = v9fs_create_common(bufp, size, TSTAT);
805         if (IS_ERR(fc))
806                 goto error;
807
808         v9fs_put_int32(bufp, fid, &fc->params.tstat.fid);
809
810         if (buf_check_overflow(bufp)) {
811                 kfree(fc);
812                 fc = ERR_PTR(-ENOMEM);
813         }
814       error:
815         return fc;
816 }
817
818 struct v9fs_fcall *v9fs_create_twstat(u32 fid, struct v9fs_wstat *wstat,
819                                       int extended)
820 {
821         int size, statsz;
822         struct v9fs_fcall *fc;
823         struct cbuf buffer;
824         struct cbuf *bufp = &buffer;
825
826         statsz = v9fs_size_wstat(wstat, extended);
827         size = 4 + 2 + 2 + statsz;      /* fid[4] stat[n] */
828         fc = v9fs_create_common(bufp, size, TWSTAT);
829         if (IS_ERR(fc))
830                 goto error;
831
832         v9fs_put_int32(bufp, fid, &fc->params.twstat.fid);
833         buf_put_int16(bufp, statsz + 2);
834         v9fs_put_wstat(bufp, wstat, &fc->params.twstat.stat, statsz, extended);
835
836         if (buf_check_overflow(bufp)) {
837                 kfree(fc);
838                 fc = ERR_PTR(-ENOMEM);
839         }
840       error:
841         return fc;
842 }