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