[TCP]: Fix some warning when MD5 is disabled.
[linux-2.6/btrfs-unstable.git] / fs / 9p / conv.c
blob56d88c1a09c566baa5a0733f728cc7a8819b97b7
1 /*
2 * linux/fs/9p/conv.c
4 * 9P protocol conversion functions
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>
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.
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.
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
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"
38 * Buffer to help with string parsing
40 struct cbuf {
41 unsigned char *sp;
42 unsigned char *p;
43 unsigned char *ep;
46 static inline void buf_init(struct cbuf *buf, void *data, int datalen)
48 buf->sp = buf->p = data;
49 buf->ep = data + datalen;
52 static inline int buf_check_overflow(struct cbuf *buf)
54 return buf->p > buf->ep;
57 static int buf_check_size(struct cbuf *buf, int len)
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;
67 return 0;
70 return 1;
73 static void *buf_alloc(struct cbuf *buf, int len)
75 void *ret = NULL;
77 if (buf_check_size(buf, len)) {
78 ret = buf->p;
79 buf->p += len;
82 return ret;
85 static void buf_put_int8(struct cbuf *buf, u8 val)
87 if (buf_check_size(buf, 1)) {
88 buf->p[0] = val;
89 buf->p++;
93 static void buf_put_int16(struct cbuf *buf, u16 val)
95 if (buf_check_size(buf, 2)) {
96 *(__le16 *) buf->p = cpu_to_le16(val);
97 buf->p += 2;
101 static void buf_put_int32(struct cbuf *buf, u32 val)
103 if (buf_check_size(buf, 4)) {
104 *(__le32 *)buf->p = cpu_to_le32(val);
105 buf->p += 4;
109 static void buf_put_int64(struct cbuf *buf, u64 val)
111 if (buf_check_size(buf, 8)) {
112 *(__le64 *)buf->p = cpu_to_le64(val);
113 buf->p += 8;
117 static char *buf_put_stringn(struct cbuf *buf, const char *s, u16 slen)
119 char *ret;
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;
129 return ret;
132 static inline void buf_put_string(struct cbuf *buf, const char *s)
134 buf_put_stringn(buf, s, strlen(s));
137 static u8 buf_get_int8(struct cbuf *buf)
139 u8 ret = 0;
141 if (buf_check_size(buf, 1)) {
142 ret = buf->p[0];
143 buf->p++;
146 return ret;
149 static u16 buf_get_int16(struct cbuf *buf)
151 u16 ret = 0;
153 if (buf_check_size(buf, 2)) {
154 ret = le16_to_cpu(*(__le16 *)buf->p);
155 buf->p += 2;
158 return ret;
161 static u32 buf_get_int32(struct cbuf *buf)
163 u32 ret = 0;
165 if (buf_check_size(buf, 4)) {
166 ret = le32_to_cpu(*(__le32 *)buf->p);
167 buf->p += 4;
170 return ret;
173 static u64 buf_get_int64(struct cbuf *buf)
175 u64 ret = 0;
177 if (buf_check_size(buf, 8)) {
178 ret = le64_to_cpu(*(__le64 *)buf->p);
179 buf->p += 8;
182 return ret;
185 static void buf_get_str(struct cbuf *buf, struct v9fs_str *vstr)
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;
197 static void buf_get_qid(struct cbuf *bufp, struct v9fs_qid *qid)
199 qid->type = buf_get_int8(bufp);
200 qid->version = buf_get_int32(bufp);
201 qid->path = buf_get_int64(bufp);
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
211 static int v9fs_size_wstat(struct v9fs_wstat *wstat, int extended)
213 int size = 0;
215 if (wstat == NULL) {
216 eprintk(KERN_ERR, "v9fs_size_stat: got a NULL stat pointer\n");
217 return 0;
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 */
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);
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);
250 return size;
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
261 static void
262 buf_get_stat(struct cbuf *bufp, struct v9fs_stat *stat, int extended)
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);
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);
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
294 * Note: stat will point to the buf region.
298 v9fs_deserialize_stat(void *buf, u32 buflen, struct v9fs_stat *stat,
299 int extended)
301 struct cbuf buffer;
302 struct cbuf *bufp = &buffer;
303 unsigned char *p;
305 buf_init(bufp, buf, buflen);
306 p = bufp->p;
307 buf_get_stat(bufp, stat, extended);
309 if (buf_check_overflow(bufp))
310 return 0;
311 else
312 return bufp->p - p;
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
326 v9fs_deserialize_fcall(void *buf, u32 buflen, struct v9fs_fcall *rcall,
327 int extended)
330 struct cbuf buffer;
331 struct cbuf *bufp = &buffer;
332 int i = 0;
334 buf_init(bufp, buf, buflen);
336 rcall->size = buf_get_int32(bufp);
337 rcall->id = buf_get_int8(bufp);
338 rcall->tag = buf_get_int16(bufp);
340 dprintk(DEBUG_CONV, "size %d id %d tag %d\n", rcall->size, rcall->id,
341 rcall->tag);
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;
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;
402 if (buf_check_overflow(bufp)) {
403 dprintk(DEBUG_ERROR, "buffer overflow\n");
404 return -EIO;
407 return bufp->p - bufp->sp;
410 static inline void v9fs_put_int8(struct cbuf *bufp, u8 val, u8 * p)
412 *p = val;
413 buf_put_int8(bufp, val);
416 static inline void v9fs_put_int16(struct cbuf *bufp, u16 val, u16 * p)
418 *p = val;
419 buf_put_int16(bufp, val);
422 static inline void v9fs_put_int32(struct cbuf *bufp, u32 val, u32 * p)
424 *p = val;
425 buf_put_int32(bufp, val);
428 static inline void v9fs_put_int64(struct cbuf *bufp, u64 val, u64 * p)
430 *p = val;
431 buf_put_int64(bufp, val);
434 static void
435 v9fs_put_str(struct cbuf *bufp, char *data, struct v9fs_str *str)
437 int len;
438 char *s;
440 if (data)
441 len = strlen(data);
442 else
443 len = 0;
445 s = buf_put_stringn(bufp, data, len);
446 if (str) {
447 str->len = len;
448 str->str = s;
452 static int
453 v9fs_put_user_data(struct cbuf *bufp, const char __user * data, int count,
454 unsigned char **pdata)
456 *pdata = buf_alloc(bufp, count);
457 return copy_from_user(*pdata, data, count);
460 static void
461 v9fs_put_wstat(struct cbuf *bufp, struct v9fs_wstat *wstat,
462 struct v9fs_stat *stat, int statsz, int extended)
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);
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);
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);
488 static struct v9fs_fcall *
489 v9fs_create_common(struct cbuf *bufp, u32 size, u8 id)
491 struct v9fs_fcall *fc;
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);
498 fc->sdata = (char *)fc + sizeof(*fc);
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);
505 return fc;
508 void v9fs_set_tag(struct v9fs_fcall *fc, u16 tag)
510 fc->tag = tag;
511 *(__le16 *) (fc->sdata + 5) = cpu_to_le16(tag);
514 struct v9fs_fcall *v9fs_create_tversion(u32 msize, char *version)
516 int size;
517 struct v9fs_fcall *fc;
518 struct cbuf buffer;
519 struct cbuf *bufp = &buffer;
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;
526 v9fs_put_int32(bufp, msize, &fc->params.tversion.msize);
527 v9fs_put_str(bufp, version, &fc->params.tversion.version);
529 if (buf_check_overflow(bufp)) {
530 kfree(fc);
531 fc = ERR_PTR(-ENOMEM);
533 error:
534 return fc;
537 #if 0
538 struct v9fs_fcall *v9fs_create_tauth(u32 afid, char *uname, char *aname)
540 int size;
541 struct v9fs_fcall *fc;
542 struct cbuf buffer;
543 struct cbuf *bufp = &buffer;
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;
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);
554 if (buf_check_overflow(bufp)) {
555 kfree(fc);
556 fc = ERR_PTR(-ENOMEM);
558 error:
559 return fc;
561 #endif /* 0 */
563 struct v9fs_fcall *
564 v9fs_create_tattach(u32 fid, u32 afid, char *uname, char *aname)
566 int size;
567 struct v9fs_fcall *fc;
568 struct cbuf buffer;
569 struct cbuf *bufp = &buffer;
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;
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);
581 error:
582 return fc;
585 struct v9fs_fcall *v9fs_create_tflush(u16 oldtag)
587 int size;
588 struct v9fs_fcall *fc;
589 struct cbuf buffer;
590 struct cbuf *bufp = &buffer;
592 size = 2; /* oldtag[2] */
593 fc = v9fs_create_common(bufp, size, TFLUSH);
594 if (IS_ERR(fc))
595 goto error;
597 v9fs_put_int16(bufp, oldtag, &fc->params.tflush.oldtag);
599 if (buf_check_overflow(bufp)) {
600 kfree(fc);
601 fc = ERR_PTR(-ENOMEM);
603 error:
604 return fc;
607 struct v9fs_fcall *v9fs_create_twalk(u32 fid, u32 newfid, u16 nwname,
608 char **wnames)
610 int i, size;
611 struct v9fs_fcall *fc;
612 struct cbuf buffer;
613 struct cbuf *bufp = &buffer;
615 if (nwname > V9FS_MAXWELEM) {
616 dprintk(DEBUG_ERROR, "nwname > %d\n", V9FS_MAXWELEM);
617 return NULL;
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] */
625 fc = v9fs_create_common(bufp, size, TWALK);
626 if (IS_ERR(fc))
627 goto error;
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]);
636 if (buf_check_overflow(bufp)) {
637 kfree(fc);
638 fc = ERR_PTR(-ENOMEM);
640 error:
641 return fc;
644 struct v9fs_fcall *v9fs_create_topen(u32 fid, u8 mode)
646 int size;
647 struct v9fs_fcall *fc;
648 struct cbuf buffer;
649 struct cbuf *bufp = &buffer;
651 size = 4 + 1; /* fid[4] mode[1] */
652 fc = v9fs_create_common(bufp, size, TOPEN);
653 if (IS_ERR(fc))
654 goto error;
656 v9fs_put_int32(bufp, fid, &fc->params.topen.fid);
657 v9fs_put_int8(bufp, mode, &fc->params.topen.mode);
659 if (buf_check_overflow(bufp)) {
660 kfree(fc);
661 fc = ERR_PTR(-ENOMEM);
663 error:
664 return fc;
667 struct v9fs_fcall *v9fs_create_tcreate(u32 fid, char *name, u32 perm, u8 mode,
668 char *extension, int extended)
670 int size;
671 struct v9fs_fcall *fc;
672 struct cbuf buffer;
673 struct cbuf *bufp = &buffer;
675 size = 4 + 2 + strlen(name) + 4 + 1; /* fid[4] name[s] perm[4] mode[1] */
676 if (extended) {
677 size += 2 + /* extension[s] */
678 (extension == NULL ? 0 : strlen(extension));
681 fc = v9fs_create_common(bufp, size, TCREATE);
682 if (IS_ERR(fc))
683 goto error;
685 v9fs_put_int32(bufp, fid, &fc->params.tcreate.fid);
686 v9fs_put_str(bufp, name, &fc->params.tcreate.name);
687 v9fs_put_int32(bufp, perm, &fc->params.tcreate.perm);
688 v9fs_put_int8(bufp, mode, &fc->params.tcreate.mode);
689 if (extended)
690 v9fs_put_str(bufp, extension, &fc->params.tcreate.extension);
692 if (buf_check_overflow(bufp)) {
693 kfree(fc);
694 fc = ERR_PTR(-ENOMEM);
696 error:
697 return fc;
700 struct v9fs_fcall *v9fs_create_tread(u32 fid, u64 offset, u32 count)
702 int size;
703 struct v9fs_fcall *fc;
704 struct cbuf buffer;
705 struct cbuf *bufp = &buffer;
707 size = 4 + 8 + 4; /* fid[4] offset[8] count[4] */
708 fc = v9fs_create_common(bufp, size, TREAD);
709 if (IS_ERR(fc))
710 goto error;
712 v9fs_put_int32(bufp, fid, &fc->params.tread.fid);
713 v9fs_put_int64(bufp, offset, &fc->params.tread.offset);
714 v9fs_put_int32(bufp, count, &fc->params.tread.count);
716 if (buf_check_overflow(bufp)) {
717 kfree(fc);
718 fc = ERR_PTR(-ENOMEM);
720 error:
721 return fc;
724 struct v9fs_fcall *v9fs_create_twrite(u32 fid, u64 offset, u32 count,
725 const char __user * data)
727 int size, err;
728 struct v9fs_fcall *fc;
729 struct cbuf buffer;
730 struct cbuf *bufp = &buffer;
732 size = 4 + 8 + 4 + count; /* fid[4] offset[8] count[4] data[count] */
733 fc = v9fs_create_common(bufp, size, TWRITE);
734 if (IS_ERR(fc))
735 goto error;
737 v9fs_put_int32(bufp, fid, &fc->params.twrite.fid);
738 v9fs_put_int64(bufp, offset, &fc->params.twrite.offset);
739 v9fs_put_int32(bufp, count, &fc->params.twrite.count);
740 err = v9fs_put_user_data(bufp, data, count, &fc->params.twrite.data);
741 if (err) {
742 kfree(fc);
743 fc = ERR_PTR(err);
746 if (buf_check_overflow(bufp)) {
747 kfree(fc);
748 fc = ERR_PTR(-ENOMEM);
750 error:
751 return fc;
754 struct v9fs_fcall *v9fs_create_tclunk(u32 fid)
756 int size;
757 struct v9fs_fcall *fc;
758 struct cbuf buffer;
759 struct cbuf *bufp = &buffer;
761 size = 4; /* fid[4] */
762 fc = v9fs_create_common(bufp, size, TCLUNK);
763 if (IS_ERR(fc))
764 goto error;
766 v9fs_put_int32(bufp, fid, &fc->params.tclunk.fid);
768 if (buf_check_overflow(bufp)) {
769 kfree(fc);
770 fc = ERR_PTR(-ENOMEM);
772 error:
773 return fc;
776 struct v9fs_fcall *v9fs_create_tremove(u32 fid)
778 int size;
779 struct v9fs_fcall *fc;
780 struct cbuf buffer;
781 struct cbuf *bufp = &buffer;
783 size = 4; /* fid[4] */
784 fc = v9fs_create_common(bufp, size, TREMOVE);
785 if (IS_ERR(fc))
786 goto error;
788 v9fs_put_int32(bufp, fid, &fc->params.tremove.fid);
790 if (buf_check_overflow(bufp)) {
791 kfree(fc);
792 fc = ERR_PTR(-ENOMEM);
794 error:
795 return fc;
798 struct v9fs_fcall *v9fs_create_tstat(u32 fid)
800 int size;
801 struct v9fs_fcall *fc;
802 struct cbuf buffer;
803 struct cbuf *bufp = &buffer;
805 size = 4; /* fid[4] */
806 fc = v9fs_create_common(bufp, size, TSTAT);
807 if (IS_ERR(fc))
808 goto error;
810 v9fs_put_int32(bufp, fid, &fc->params.tstat.fid);
812 if (buf_check_overflow(bufp)) {
813 kfree(fc);
814 fc = ERR_PTR(-ENOMEM);
816 error:
817 return fc;
820 struct v9fs_fcall *v9fs_create_twstat(u32 fid, struct v9fs_wstat *wstat,
821 int extended)
823 int size, statsz;
824 struct v9fs_fcall *fc;
825 struct cbuf buffer;
826 struct cbuf *bufp = &buffer;
828 statsz = v9fs_size_wstat(wstat, extended);
829 size = 4 + 2 + 2 + statsz; /* fid[4] stat[n] */
830 fc = v9fs_create_common(bufp, size, TWSTAT);
831 if (IS_ERR(fc))
832 goto error;
834 v9fs_put_int32(bufp, fid, &fc->params.twstat.fid);
835 buf_put_int16(bufp, statsz + 2);
836 v9fs_put_wstat(bufp, wstat, &fc->params.twstat.stat, statsz, extended);
838 if (buf_check_overflow(bufp)) {
839 kfree(fc);
840 fc = ERR_PTR(-ENOMEM);
842 error:
843 return fc;