Merge branch 'from-linus' into upstream
[deliverable/linux.git] / 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) {
677 size += 2 + /* extension[s] */
678 (extension == NULL ? 0 : strlen(extension));
679 }
680
681 fc = v9fs_create_common(bufp, size, TCREATE);
682 if (IS_ERR(fc))
683 goto error;
684
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);
691
692 if (buf_check_overflow(bufp)) {
693 kfree(fc);
694 fc = ERR_PTR(-ENOMEM);
695 }
696 error:
697 return fc;
698 }
699
700 struct v9fs_fcall *v9fs_create_tread(u32 fid, u64 offset, u32 count)
701 {
702 int size;
703 struct v9fs_fcall *fc;
704 struct cbuf buffer;
705 struct cbuf *bufp = &buffer;
706
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;
711
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);
715
716 if (buf_check_overflow(bufp)) {
717 kfree(fc);
718 fc = ERR_PTR(-ENOMEM);
719 }
720 error:
721 return fc;
722 }
723
724 struct v9fs_fcall *v9fs_create_twrite(u32 fid, u64 offset, u32 count,
725 const char __user * data)
726 {
727 int size, err;
728 struct v9fs_fcall *fc;
729 struct cbuf buffer;
730 struct cbuf *bufp = &buffer;
731
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;
736
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);
744 }
745
746 if (buf_check_overflow(bufp)) {
747 kfree(fc);
748 fc = ERR_PTR(-ENOMEM);
749 }
750 error:
751 return fc;
752 }
753
754 struct v9fs_fcall *v9fs_create_tclunk(u32 fid)
755 {
756 int size;
757 struct v9fs_fcall *fc;
758 struct cbuf buffer;
759 struct cbuf *bufp = &buffer;
760
761 size = 4; /* fid[4] */
762 fc = v9fs_create_common(bufp, size, TCLUNK);
763 if (IS_ERR(fc))
764 goto error;
765
766 v9fs_put_int32(bufp, fid, &fc->params.tclunk.fid);
767
768 if (buf_check_overflow(bufp)) {
769 kfree(fc);
770 fc = ERR_PTR(-ENOMEM);
771 }
772 error:
773 return fc;
774 }
775
776 struct v9fs_fcall *v9fs_create_tremove(u32 fid)
777 {
778 int size;
779 struct v9fs_fcall *fc;
780 struct cbuf buffer;
781 struct cbuf *bufp = &buffer;
782
783 size = 4; /* fid[4] */
784 fc = v9fs_create_common(bufp, size, TREMOVE);
785 if (IS_ERR(fc))
786 goto error;
787
788 v9fs_put_int32(bufp, fid, &fc->params.tremove.fid);
789
790 if (buf_check_overflow(bufp)) {
791 kfree(fc);
792 fc = ERR_PTR(-ENOMEM);
793 }
794 error:
795 return fc;
796 }
797
798 struct v9fs_fcall *v9fs_create_tstat(u32 fid)
799 {
800 int size;
801 struct v9fs_fcall *fc;
802 struct cbuf buffer;
803 struct cbuf *bufp = &buffer;
804
805 size = 4; /* fid[4] */
806 fc = v9fs_create_common(bufp, size, TSTAT);
807 if (IS_ERR(fc))
808 goto error;
809
810 v9fs_put_int32(bufp, fid, &fc->params.tstat.fid);
811
812 if (buf_check_overflow(bufp)) {
813 kfree(fc);
814 fc = ERR_PTR(-ENOMEM);
815 }
816 error:
817 return fc;
818 }
819
820 struct v9fs_fcall *v9fs_create_twstat(u32 fid, struct v9fs_wstat *wstat,
821 int extended)
822 {
823 int size, statsz;
824 struct v9fs_fcall *fc;
825 struct cbuf buffer;
826 struct cbuf *bufp = &buffer;
827
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;
833
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);
837
838 if (buf_check_overflow(bufp)) {
839 kfree(fc);
840 fc = ERR_PTR(-ENOMEM);
841 }
842 error:
843 return fc;
844 }
This page took 0.060277 seconds and 6 git commands to generate.