aboutsummaryrefslogtreecommitdiffstats
path: root/net/9p/protocol.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/9p/protocol.c')
-rw-r--r--net/9p/protocol.c151
1 files changed, 117 insertions, 34 deletions
diff --git a/net/9p/protocol.c b/net/9p/protocol.c
index fc70147c771e..3acd3afb20c8 100644
--- a/net/9p/protocol.c
+++ b/net/9p/protocol.c
@@ -28,6 +28,7 @@
28#include <linux/module.h> 28#include <linux/module.h>
29#include <linux/errno.h> 29#include <linux/errno.h>
30#include <linux/uaccess.h> 30#include <linux/uaccess.h>
31#include <linux/slab.h>
31#include <linux/sched.h> 32#include <linux/sched.h>
32#include <linux/types.h> 33#include <linux/types.h>
33#include <net/9p/9p.h> 34#include <net/9p/9p.h>
@@ -52,7 +53,7 @@
52#endif 53#endif
53 54
54static int 55static int
55p9pdu_writef(struct p9_fcall *pdu, int optional, const char *fmt, ...); 56p9pdu_writef(struct p9_fcall *pdu, int proto_version, const char *fmt, ...);
56 57
57#ifdef CONFIG_NET_9P_DEBUG 58#ifdef CONFIG_NET_9P_DEBUG
58void 59void
@@ -140,11 +141,13 @@ pdu_write_u(struct p9_fcall *pdu, const char __user *udata, size_t size)
140 D - data blob (int32_t size followed by void *, results are not freed) 141 D - data blob (int32_t size followed by void *, results are not freed)
141 T - array of strings (int16_t count, followed by strings) 142 T - array of strings (int16_t count, followed by strings)
142 R - array of qids (int16_t count, followed by qids) 143 R - array of qids (int16_t count, followed by qids)
144 A - stat for 9p2000.L (p9_stat_dotl)
143 ? - if optional = 1, continue parsing 145 ? - if optional = 1, continue parsing
144*/ 146*/
145 147
146static int 148static int
147p9pdu_vreadf(struct p9_fcall *pdu, int optional, const char *fmt, va_list ap) 149p9pdu_vreadf(struct p9_fcall *pdu, int proto_version, const char *fmt,
150 va_list ap)
148{ 151{
149 const char *ptr; 152 const char *ptr;
150 int errcode = 0; 153 int errcode = 0;
@@ -194,7 +197,8 @@ p9pdu_vreadf(struct p9_fcall *pdu, int optional, const char *fmt, va_list ap)
194 int16_t len; 197 int16_t len;
195 int size; 198 int size;
196 199
197 errcode = p9pdu_readf(pdu, optional, "w", &len); 200 errcode = p9pdu_readf(pdu, proto_version,
201 "w", &len);
198 if (errcode) 202 if (errcode)
199 break; 203 break;
200 204
@@ -217,7 +221,7 @@ p9pdu_vreadf(struct p9_fcall *pdu, int optional, const char *fmt, va_list ap)
217 struct p9_qid *qid = 221 struct p9_qid *qid =
218 va_arg(ap, struct p9_qid *); 222 va_arg(ap, struct p9_qid *);
219 223
220 errcode = p9pdu_readf(pdu, optional, "bdq", 224 errcode = p9pdu_readf(pdu, proto_version, "bdq",
221 &qid->type, &qid->version, 225 &qid->type, &qid->version,
222 &qid->path); 226 &qid->path);
223 } 227 }
@@ -230,7 +234,7 @@ p9pdu_vreadf(struct p9_fcall *pdu, int optional, const char *fmt, va_list ap)
230 stbuf->n_uid = stbuf->n_gid = stbuf->n_muid = 234 stbuf->n_uid = stbuf->n_gid = stbuf->n_muid =
231 -1; 235 -1;
232 errcode = 236 errcode =
233 p9pdu_readf(pdu, optional, 237 p9pdu_readf(pdu, proto_version,
234 "wwdQdddqssss?sddd", 238 "wwdQdddqssss?sddd",
235 &stbuf->size, &stbuf->type, 239 &stbuf->size, &stbuf->type,
236 &stbuf->dev, &stbuf->qid, 240 &stbuf->dev, &stbuf->qid,
@@ -250,7 +254,7 @@ p9pdu_vreadf(struct p9_fcall *pdu, int optional, const char *fmt, va_list ap)
250 void **data = va_arg(ap, void **); 254 void **data = va_arg(ap, void **);
251 255
252 errcode = 256 errcode =
253 p9pdu_readf(pdu, optional, "d", count); 257 p9pdu_readf(pdu, proto_version, "d", count);
254 if (!errcode) { 258 if (!errcode) {
255 *count = 259 *count =
256 MIN(*count, 260 MIN(*count,
@@ -263,8 +267,8 @@ p9pdu_vreadf(struct p9_fcall *pdu, int optional, const char *fmt, va_list ap)
263 int16_t *nwname = va_arg(ap, int16_t *); 267 int16_t *nwname = va_arg(ap, int16_t *);
264 char ***wnames = va_arg(ap, char ***); 268 char ***wnames = va_arg(ap, char ***);
265 269
266 errcode = 270 errcode = p9pdu_readf(pdu, proto_version,
267 p9pdu_readf(pdu, optional, "w", nwname); 271 "w", nwname);
268 if (!errcode) { 272 if (!errcode) {
269 *wnames = 273 *wnames =
270 kmalloc(sizeof(char *) * *nwname, 274 kmalloc(sizeof(char *) * *nwname,
@@ -278,7 +282,8 @@ p9pdu_vreadf(struct p9_fcall *pdu, int optional, const char *fmt, va_list ap)
278 282
279 for (i = 0; i < *nwname; i++) { 283 for (i = 0; i < *nwname; i++) {
280 errcode = 284 errcode =
281 p9pdu_readf(pdu, optional, 285 p9pdu_readf(pdu,
286 proto_version,
282 "s", 287 "s",
283 &(*wnames)[i]); 288 &(*wnames)[i]);
284 if (errcode) 289 if (errcode)
@@ -306,7 +311,7 @@ p9pdu_vreadf(struct p9_fcall *pdu, int optional, const char *fmt, va_list ap)
306 *wqids = NULL; 311 *wqids = NULL;
307 312
308 errcode = 313 errcode =
309 p9pdu_readf(pdu, optional, "w", nwqid); 314 p9pdu_readf(pdu, proto_version, "w", nwqid);
310 if (!errcode) { 315 if (!errcode) {
311 *wqids = 316 *wqids =
312 kmalloc(*nwqid * 317 kmalloc(*nwqid *
@@ -321,7 +326,8 @@ p9pdu_vreadf(struct p9_fcall *pdu, int optional, const char *fmt, va_list ap)
321 326
322 for (i = 0; i < *nwqid; i++) { 327 for (i = 0; i < *nwqid; i++) {
323 errcode = 328 errcode =
324 p9pdu_readf(pdu, optional, 329 p9pdu_readf(pdu,
330 proto_version,
325 "Q", 331 "Q",
326 &(*wqids)[i]); 332 &(*wqids)[i]);
327 if (errcode) 333 if (errcode)
@@ -335,8 +341,36 @@ p9pdu_vreadf(struct p9_fcall *pdu, int optional, const char *fmt, va_list ap)
335 } 341 }
336 } 342 }
337 break; 343 break;
344 case 'A': {
345 struct p9_stat_dotl *stbuf =
346 va_arg(ap, struct p9_stat_dotl *);
347
348 memset(stbuf, 0, sizeof(struct p9_stat_dotl));
349 errcode =
350 p9pdu_readf(pdu, proto_version,
351 "qQdddqqqqqqqqqqqqqqq",
352 &stbuf->st_result_mask,
353 &stbuf->qid,
354 &stbuf->st_mode,
355 &stbuf->st_uid, &stbuf->st_gid,
356 &stbuf->st_nlink,
357 &stbuf->st_rdev, &stbuf->st_size,
358 &stbuf->st_blksize, &stbuf->st_blocks,
359 &stbuf->st_atime_sec,
360 &stbuf->st_atime_nsec,
361 &stbuf->st_mtime_sec,
362 &stbuf->st_mtime_nsec,
363 &stbuf->st_ctime_sec,
364 &stbuf->st_ctime_nsec,
365 &stbuf->st_btime_sec,
366 &stbuf->st_btime_nsec,
367 &stbuf->st_gen,
368 &stbuf->st_data_version);
369 }
370 break;
338 case '?': 371 case '?':
339 if (!optional) 372 if ((proto_version != p9_proto_2000u) &&
373 (proto_version != p9_proto_2000L))
340 return 0; 374 return 0;
341 break; 375 break;
342 default: 376 default:
@@ -352,7 +386,8 @@ p9pdu_vreadf(struct p9_fcall *pdu, int optional, const char *fmt, va_list ap)
352} 386}
353 387
354int 388int
355p9pdu_vwritef(struct p9_fcall *pdu, int optional, const char *fmt, va_list ap) 389p9pdu_vwritef(struct p9_fcall *pdu, int proto_version, const char *fmt,
390 va_list ap)
356{ 391{
357 const char *ptr; 392 const char *ptr;
358 int errcode = 0; 393 int errcode = 0;
@@ -387,9 +422,10 @@ p9pdu_vwritef(struct p9_fcall *pdu, int optional, const char *fmt, va_list ap)
387 const char *sptr = va_arg(ap, const char *); 422 const char *sptr = va_arg(ap, const char *);
388 int16_t len = 0; 423 int16_t len = 0;
389 if (sptr) 424 if (sptr)
390 len = MIN(strlen(sptr), USHORT_MAX); 425 len = MIN(strlen(sptr), USHRT_MAX);
391 426
392 errcode = p9pdu_writef(pdu, optional, "w", len); 427 errcode = p9pdu_writef(pdu, proto_version,
428 "w", len);
393 if (!errcode && pdu_write(pdu, sptr, len)) 429 if (!errcode && pdu_write(pdu, sptr, len))
394 errcode = -EFAULT; 430 errcode = -EFAULT;
395 } 431 }
@@ -398,7 +434,7 @@ p9pdu_vwritef(struct p9_fcall *pdu, int optional, const char *fmt, va_list ap)
398 const struct p9_qid *qid = 434 const struct p9_qid *qid =
399 va_arg(ap, const struct p9_qid *); 435 va_arg(ap, const struct p9_qid *);
400 errcode = 436 errcode =
401 p9pdu_writef(pdu, optional, "bdq", 437 p9pdu_writef(pdu, proto_version, "bdq",
402 qid->type, qid->version, 438 qid->type, qid->version,
403 qid->path); 439 qid->path);
404 } break; 440 } break;
@@ -406,7 +442,7 @@ p9pdu_vwritef(struct p9_fcall *pdu, int optional, const char *fmt, va_list ap)
406 const struct p9_wstat *stbuf = 442 const struct p9_wstat *stbuf =
407 va_arg(ap, const struct p9_wstat *); 443 va_arg(ap, const struct p9_wstat *);
408 errcode = 444 errcode =
409 p9pdu_writef(pdu, optional, 445 p9pdu_writef(pdu, proto_version,
410 "wwdQdddqssss?sddd", 446 "wwdQdddqssss?sddd",
411 stbuf->size, stbuf->type, 447 stbuf->size, stbuf->type,
412 stbuf->dev, &stbuf->qid, 448 stbuf->dev, &stbuf->qid,
@@ -421,8 +457,8 @@ p9pdu_vwritef(struct p9_fcall *pdu, int optional, const char *fmt, va_list ap)
421 int32_t count = va_arg(ap, int32_t); 457 int32_t count = va_arg(ap, int32_t);
422 const void *data = va_arg(ap, const void *); 458 const void *data = va_arg(ap, const void *);
423 459
424 errcode = 460 errcode = p9pdu_writef(pdu, proto_version, "d",
425 p9pdu_writef(pdu, optional, "d", count); 461 count);
426 if (!errcode && pdu_write(pdu, data, count)) 462 if (!errcode && pdu_write(pdu, data, count))
427 errcode = -EFAULT; 463 errcode = -EFAULT;
428 } 464 }
@@ -431,8 +467,8 @@ p9pdu_vwritef(struct p9_fcall *pdu, int optional, const char *fmt, va_list ap)
431 int32_t count = va_arg(ap, int32_t); 467 int32_t count = va_arg(ap, int32_t);
432 const char __user *udata = 468 const char __user *udata =
433 va_arg(ap, const void __user *); 469 va_arg(ap, const void __user *);
434 errcode = 470 errcode = p9pdu_writef(pdu, proto_version, "d",
435 p9pdu_writef(pdu, optional, "d", count); 471 count);
436 if (!errcode && pdu_write_u(pdu, udata, count)) 472 if (!errcode && pdu_write_u(pdu, udata, count))
437 errcode = -EFAULT; 473 errcode = -EFAULT;
438 } 474 }
@@ -441,14 +477,15 @@ p9pdu_vwritef(struct p9_fcall *pdu, int optional, const char *fmt, va_list ap)
441 int16_t nwname = va_arg(ap, int); 477 int16_t nwname = va_arg(ap, int);
442 const char **wnames = va_arg(ap, const char **); 478 const char **wnames = va_arg(ap, const char **);
443 479
444 errcode = 480 errcode = p9pdu_writef(pdu, proto_version, "w",
445 p9pdu_writef(pdu, optional, "w", nwname); 481 nwname);
446 if (!errcode) { 482 if (!errcode) {
447 int i; 483 int i;
448 484
449 for (i = 0; i < nwname; i++) { 485 for (i = 0; i < nwname; i++) {
450 errcode = 486 errcode =
451 p9pdu_writef(pdu, optional, 487 p9pdu_writef(pdu,
488 proto_version,
452 "s", 489 "s",
453 wnames[i]); 490 wnames[i]);
454 if (errcode) 491 if (errcode)
@@ -462,14 +499,15 @@ p9pdu_vwritef(struct p9_fcall *pdu, int optional, const char *fmt, va_list ap)
462 struct p9_qid *wqids = 499 struct p9_qid *wqids =
463 va_arg(ap, struct p9_qid *); 500 va_arg(ap, struct p9_qid *);
464 501
465 errcode = 502 errcode = p9pdu_writef(pdu, proto_version, "w",
466 p9pdu_writef(pdu, optional, "w", nwqid); 503 nwqid);
467 if (!errcode) { 504 if (!errcode) {
468 int i; 505 int i;
469 506
470 for (i = 0; i < nwqid; i++) { 507 for (i = 0; i < nwqid; i++) {
471 errcode = 508 errcode =
472 p9pdu_writef(pdu, optional, 509 p9pdu_writef(pdu,
510 proto_version,
473 "Q", 511 "Q",
474 &wqids[i]); 512 &wqids[i]);
475 if (errcode) 513 if (errcode)
@@ -478,8 +516,26 @@ p9pdu_vwritef(struct p9_fcall *pdu, int optional, const char *fmt, va_list ap)
478 } 516 }
479 } 517 }
480 break; 518 break;
519 case 'I':{
520 struct p9_iattr_dotl *p9attr = va_arg(ap,
521 struct p9_iattr_dotl *);
522
523 errcode = p9pdu_writef(pdu, proto_version,
524 "ddddqqqqq",
525 p9attr->valid,
526 p9attr->mode,
527 p9attr->uid,
528 p9attr->gid,
529 p9attr->size,
530 p9attr->atime_sec,
531 p9attr->atime_nsec,
532 p9attr->mtime_sec,
533 p9attr->mtime_nsec);
534 }
535 break;
481 case '?': 536 case '?':
482 if (!optional) 537 if ((proto_version != p9_proto_2000u) &&
538 (proto_version != p9_proto_2000L))
483 return 0; 539 return 0;
484 break; 540 break;
485 default: 541 default:
@@ -494,32 +550,32 @@ p9pdu_vwritef(struct p9_fcall *pdu, int optional, const char *fmt, va_list ap)
494 return errcode; 550 return errcode;
495} 551}
496 552
497int p9pdu_readf(struct p9_fcall *pdu, int optional, const char *fmt, ...) 553int p9pdu_readf(struct p9_fcall *pdu, int proto_version, const char *fmt, ...)
498{ 554{
499 va_list ap; 555 va_list ap;
500 int ret; 556 int ret;
501 557
502 va_start(ap, fmt); 558 va_start(ap, fmt);
503 ret = p9pdu_vreadf(pdu, optional, fmt, ap); 559 ret = p9pdu_vreadf(pdu, proto_version, fmt, ap);
504 va_end(ap); 560 va_end(ap);
505 561
506 return ret; 562 return ret;
507} 563}
508 564
509static int 565static int
510p9pdu_writef(struct p9_fcall *pdu, int optional, const char *fmt, ...) 566p9pdu_writef(struct p9_fcall *pdu, int proto_version, const char *fmt, ...)
511{ 567{
512 va_list ap; 568 va_list ap;
513 int ret; 569 int ret;
514 570
515 va_start(ap, fmt); 571 va_start(ap, fmt);
516 ret = p9pdu_vwritef(pdu, optional, fmt, ap); 572 ret = p9pdu_vwritef(pdu, proto_version, fmt, ap);
517 va_end(ap); 573 va_end(ap);
518 574
519 return ret; 575 return ret;
520} 576}
521 577
522int p9stat_read(char *buf, int len, struct p9_wstat *st, int dotu) 578int p9stat_read(char *buf, int len, struct p9_wstat *st, int proto_version)
523{ 579{
524 struct p9_fcall fake_pdu; 580 struct p9_fcall fake_pdu;
525 int ret; 581 int ret;
@@ -529,7 +585,7 @@ int p9stat_read(char *buf, int len, struct p9_wstat *st, int dotu)
529 fake_pdu.sdata = buf; 585 fake_pdu.sdata = buf;
530 fake_pdu.offset = 0; 586 fake_pdu.offset = 0;
531 587
532 ret = p9pdu_readf(&fake_pdu, dotu, "S", st); 588 ret = p9pdu_readf(&fake_pdu, proto_version, "S", st);
533 if (ret) { 589 if (ret) {
534 P9_DPRINTK(P9_DEBUG_9P, "<<< p9stat_read failed: %d\n", ret); 590 P9_DPRINTK(P9_DEBUG_9P, "<<< p9stat_read failed: %d\n", ret);
535 p9pdu_dump(1, &fake_pdu); 591 p9pdu_dump(1, &fake_pdu);
@@ -569,3 +625,30 @@ void p9pdu_reset(struct p9_fcall *pdu)
569 pdu->offset = 0; 625 pdu->offset = 0;
570 pdu->size = 0; 626 pdu->size = 0;
571} 627}
628
629int p9dirent_read(char *buf, int len, struct p9_dirent *dirent,
630 int proto_version)
631{
632 struct p9_fcall fake_pdu;
633 int ret;
634 char *nameptr;
635
636 fake_pdu.size = len;
637 fake_pdu.capacity = len;
638 fake_pdu.sdata = buf;
639 fake_pdu.offset = 0;
640
641 ret = p9pdu_readf(&fake_pdu, proto_version, "Qqbs", &dirent->qid,
642 &dirent->d_off, &dirent->d_type, &nameptr);
643 if (ret) {
644 P9_DPRINTK(P9_DEBUG_9P, "<<< p9dirent_read failed: %d\n", ret);
645 p9pdu_dump(1, &fake_pdu);
646 goto out;
647 }
648
649 strcpy(dirent->d_name, nameptr);
650
651out:
652 return fake_pdu.offset;
653}
654EXPORT_SYMBOL(p9dirent_read);