diff options
Diffstat (limited to 'net/9p/protocol.c')
-rw-r--r-- | net/9p/protocol.c | 55 |
1 files changed, 50 insertions, 5 deletions
diff --git a/net/9p/protocol.c b/net/9p/protocol.c index 1e308f210928..b58a501cf3d1 100644 --- a/net/9p/protocol.c +++ b/net/9p/protocol.c | |||
@@ -114,6 +114,26 @@ pdu_write_u(struct p9_fcall *pdu, const char __user *udata, size_t size) | |||
114 | return size - len; | 114 | return size - len; |
115 | } | 115 | } |
116 | 116 | ||
117 | static size_t | ||
118 | pdu_write_urw(struct p9_fcall *pdu, const char *kdata, const char __user *udata, | ||
119 | size_t size) | ||
120 | { | ||
121 | BUG_ON(pdu->size > P9_IOHDRSZ); | ||
122 | pdu->pubuf = (char __user *)udata; | ||
123 | pdu->pkbuf = (char *)kdata; | ||
124 | pdu->pbuf_size = size; | ||
125 | return 0; | ||
126 | } | ||
127 | |||
128 | static size_t | ||
129 | pdu_write_readdir(struct p9_fcall *pdu, const char *kdata, size_t size) | ||
130 | { | ||
131 | BUG_ON(pdu->size > P9_READDIRHDRSZ); | ||
132 | pdu->pkbuf = (char *)kdata; | ||
133 | pdu->pbuf_size = size; | ||
134 | return 0; | ||
135 | } | ||
136 | |||
117 | /* | 137 | /* |
118 | b - int8_t | 138 | b - int8_t |
119 | w - int16_t | 139 | w - int16_t |
@@ -185,7 +205,7 @@ p9pdu_vreadf(struct p9_fcall *pdu, int proto_version, const char *fmt, | |||
185 | if (errcode) | 205 | if (errcode) |
186 | break; | 206 | break; |
187 | 207 | ||
188 | *sptr = kmalloc(len + 1, GFP_KERNEL); | 208 | *sptr = kmalloc(len + 1, GFP_NOFS); |
189 | if (*sptr == NULL) { | 209 | if (*sptr == NULL) { |
190 | errcode = -EFAULT; | 210 | errcode = -EFAULT; |
191 | break; | 211 | break; |
@@ -245,7 +265,7 @@ p9pdu_vreadf(struct p9_fcall *pdu, int proto_version, const char *fmt, | |||
245 | } | 265 | } |
246 | break; | 266 | break; |
247 | case 'T':{ | 267 | case 'T':{ |
248 | int16_t *nwname = va_arg(ap, int16_t *); | 268 | uint16_t *nwname = va_arg(ap, uint16_t *); |
249 | char ***wnames = va_arg(ap, char ***); | 269 | char ***wnames = va_arg(ap, char ***); |
250 | 270 | ||
251 | errcode = p9pdu_readf(pdu, proto_version, | 271 | errcode = p9pdu_readf(pdu, proto_version, |
@@ -253,7 +273,7 @@ p9pdu_vreadf(struct p9_fcall *pdu, int proto_version, const char *fmt, | |||
253 | if (!errcode) { | 273 | if (!errcode) { |
254 | *wnames = | 274 | *wnames = |
255 | kmalloc(sizeof(char *) * *nwname, | 275 | kmalloc(sizeof(char *) * *nwname, |
256 | GFP_KERNEL); | 276 | GFP_NOFS); |
257 | if (!*wnames) | 277 | if (!*wnames) |
258 | errcode = -ENOMEM; | 278 | errcode = -ENOMEM; |
259 | } | 279 | } |
@@ -297,7 +317,7 @@ p9pdu_vreadf(struct p9_fcall *pdu, int proto_version, const char *fmt, | |||
297 | *wqids = | 317 | *wqids = |
298 | kmalloc(*nwqid * | 318 | kmalloc(*nwqid * |
299 | sizeof(struct p9_qid), | 319 | sizeof(struct p9_qid), |
300 | GFP_KERNEL); | 320 | GFP_NOFS); |
301 | if (*wqids == NULL) | 321 | if (*wqids == NULL) |
302 | errcode = -ENOMEM; | 322 | errcode = -ENOMEM; |
303 | } | 323 | } |
@@ -445,6 +465,26 @@ p9pdu_vwritef(struct p9_fcall *pdu, int proto_version, const char *fmt, | |||
445 | errcode = -EFAULT; | 465 | errcode = -EFAULT; |
446 | } | 466 | } |
447 | break; | 467 | break; |
468 | case 'E':{ | ||
469 | int32_t cnt = va_arg(ap, int32_t); | ||
470 | const char *k = va_arg(ap, const void *); | ||
471 | const char __user *u = va_arg(ap, | ||
472 | const void __user *); | ||
473 | errcode = p9pdu_writef(pdu, proto_version, "d", | ||
474 | cnt); | ||
475 | if (!errcode && pdu_write_urw(pdu, k, u, cnt)) | ||
476 | errcode = -EFAULT; | ||
477 | } | ||
478 | break; | ||
479 | case 'F':{ | ||
480 | int32_t cnt = va_arg(ap, int32_t); | ||
481 | const char *k = va_arg(ap, const void *); | ||
482 | errcode = p9pdu_writef(pdu, proto_version, "d", | ||
483 | cnt); | ||
484 | if (!errcode && pdu_write_readdir(pdu, k, cnt)) | ||
485 | errcode = -EFAULT; | ||
486 | } | ||
487 | break; | ||
448 | case 'U':{ | 488 | case 'U':{ |
449 | int32_t count = va_arg(ap, int32_t); | 489 | int32_t count = va_arg(ap, int32_t); |
450 | const char __user *udata = | 490 | const char __user *udata = |
@@ -456,7 +496,7 @@ p9pdu_vwritef(struct p9_fcall *pdu, int proto_version, const char *fmt, | |||
456 | } | 496 | } |
457 | break; | 497 | break; |
458 | case 'T':{ | 498 | case 'T':{ |
459 | int16_t nwname = va_arg(ap, int); | 499 | uint16_t nwname = va_arg(ap, int); |
460 | const char **wnames = va_arg(ap, const char **); | 500 | const char **wnames = va_arg(ap, const char **); |
461 | 501 | ||
462 | errcode = p9pdu_writef(pdu, proto_version, "w", | 502 | errcode = p9pdu_writef(pdu, proto_version, "w", |
@@ -579,6 +619,7 @@ EXPORT_SYMBOL(p9stat_read); | |||
579 | 619 | ||
580 | int p9pdu_prepare(struct p9_fcall *pdu, int16_t tag, int8_t type) | 620 | int p9pdu_prepare(struct p9_fcall *pdu, int16_t tag, int8_t type) |
581 | { | 621 | { |
622 | pdu->id = type; | ||
582 | return p9pdu_writef(pdu, 0, "dbw", 0, type, tag); | 623 | return p9pdu_writef(pdu, 0, "dbw", 0, type, tag); |
583 | } | 624 | } |
584 | 625 | ||
@@ -606,6 +647,10 @@ void p9pdu_reset(struct p9_fcall *pdu) | |||
606 | { | 647 | { |
607 | pdu->offset = 0; | 648 | pdu->offset = 0; |
608 | pdu->size = 0; | 649 | pdu->size = 0; |
650 | pdu->private = NULL; | ||
651 | pdu->pubuf = NULL; | ||
652 | pdu->pkbuf = NULL; | ||
653 | pdu->pbuf_size = 0; | ||
609 | } | 654 | } |
610 | 655 | ||
611 | int p9dirent_read(char *buf, int len, struct p9_dirent *dirent, | 656 | int p9dirent_read(char *buf, int len, struct p9_dirent *dirent, |