diff options
author | Latchesar Ionkov <lucho@ionkov.net> | 2006-01-08 04:04:58 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-01-08 23:14:05 -0500 |
commit | 3cf6429a26da5c4d7b795e6d0f8f56ed2e4fdfc0 (patch) | |
tree | a8d856763fd9a0536519634c93ab92da684107fa /fs/9p/conv.c | |
parent | f5ef3c105bee3a52486d7b55cef3330fcde9bca6 (diff) |
[PATCH] v9fs: new multiplexer implementation
New multiplexer implementation. Decreases the number of kernel threads
required. Better handling when the user process receives a signal.
Signed-off-by: Latchesar Ionkov <lucho@ionkov.net>
Cc: Eric Van Hensbergen <ericvh@ericvh.myip.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'fs/9p/conv.c')
-rw-r--r-- | fs/9p/conv.c | 86 |
1 files changed, 45 insertions, 41 deletions
diff --git a/fs/9p/conv.c b/fs/9p/conv.c index 18121af99d3e..1b9b15dfeaf0 100644 --- a/fs/9p/conv.c +++ b/fs/9p/conv.c | |||
@@ -208,7 +208,7 @@ static inline char *buf_get_stringb(struct cbuf *buf, struct cbuf *sbuf) | |||
208 | len = buf_get_int16(buf); | 208 | len = buf_get_int16(buf); |
209 | 209 | ||
210 | if (!buf_check_overflow(buf) && buf_check_size(buf, len) && | 210 | if (!buf_check_overflow(buf) && buf_check_size(buf, len) && |
211 | buf_check_size(sbuf, len+1)) { | 211 | buf_check_size(sbuf, len + 1)) { |
212 | 212 | ||
213 | memcpy(sbuf->p, buf->p, len); | 213 | memcpy(sbuf->p, buf->p, len); |
214 | sbuf->p[len] = 0; | 214 | sbuf->p[len] = 0; |
@@ -252,13 +252,12 @@ static inline void *buf_get_datab(struct cbuf *buf, struct cbuf *dbuf, | |||
252 | 252 | ||
253 | /** | 253 | /** |
254 | * v9fs_size_stat - calculate the size of a variable length stat struct | 254 | * v9fs_size_stat - calculate the size of a variable length stat struct |
255 | * @v9ses: session information | ||
256 | * @stat: metadata (stat) structure | 255 | * @stat: metadata (stat) structure |
256 | * @extended: non-zero if 9P2000.u | ||
257 | * | 257 | * |
258 | */ | 258 | */ |
259 | 259 | ||
260 | static int v9fs_size_stat(struct v9fs_session_info *v9ses, | 260 | static int v9fs_size_stat(struct v9fs_stat *stat, int extended) |
261 | struct v9fs_stat *stat) | ||
262 | { | 261 | { |
263 | int size = 0; | 262 | int size = 0; |
264 | 263 | ||
@@ -288,7 +287,7 @@ static int v9fs_size_stat(struct v9fs_session_info *v9ses, | |||
288 | if (stat->muid) | 287 | if (stat->muid) |
289 | size += strlen(stat->muid); | 288 | size += strlen(stat->muid); |
290 | 289 | ||
291 | if (v9ses->extended) { | 290 | if (extended) { |
292 | size += 4 + /* n_uid[4] */ | 291 | size += 4 + /* n_uid[4] */ |
293 | 4 + /* n_gid[4] */ | 292 | 4 + /* n_gid[4] */ |
294 | 4 + /* n_muid[4] */ | 293 | 4 + /* n_muid[4] */ |
@@ -302,15 +301,14 @@ static int v9fs_size_stat(struct v9fs_session_info *v9ses, | |||
302 | 301 | ||
303 | /** | 302 | /** |
304 | * serialize_stat - safely format a stat structure for transmission | 303 | * serialize_stat - safely format a stat structure for transmission |
305 | * @v9ses: session info | ||
306 | * @stat: metadata (stat) structure | 304 | * @stat: metadata (stat) structure |
307 | * @bufp: buffer to serialize structure into | 305 | * @bufp: buffer to serialize structure into |
306 | * @extended: non-zero if 9P2000.u | ||
308 | * | 307 | * |
309 | */ | 308 | */ |
310 | 309 | ||
311 | static int | 310 | static int |
312 | serialize_stat(struct v9fs_session_info *v9ses, struct v9fs_stat *stat, | 311 | serialize_stat(struct v9fs_stat *stat, struct cbuf *bufp, int extended) |
313 | struct cbuf *bufp) | ||
314 | { | 312 | { |
315 | buf_put_int16(bufp, stat->size); | 313 | buf_put_int16(bufp, stat->size); |
316 | buf_put_int16(bufp, stat->type); | 314 | buf_put_int16(bufp, stat->type); |
@@ -328,7 +326,7 @@ serialize_stat(struct v9fs_session_info *v9ses, struct v9fs_stat *stat, | |||
328 | buf_put_string(bufp, stat->gid); | 326 | buf_put_string(bufp, stat->gid); |
329 | buf_put_string(bufp, stat->muid); | 327 | buf_put_string(bufp, stat->muid); |
330 | 328 | ||
331 | if (v9ses->extended) { | 329 | if (extended) { |
332 | buf_put_string(bufp, stat->extension); | 330 | buf_put_string(bufp, stat->extension); |
333 | buf_put_int32(bufp, stat->n_uid); | 331 | buf_put_int32(bufp, stat->n_uid); |
334 | buf_put_int32(bufp, stat->n_gid); | 332 | buf_put_int32(bufp, stat->n_gid); |
@@ -343,16 +341,16 @@ serialize_stat(struct v9fs_session_info *v9ses, struct v9fs_stat *stat, | |||
343 | 341 | ||
344 | /** | 342 | /** |
345 | * deserialize_stat - safely decode a recieved metadata (stat) structure | 343 | * deserialize_stat - safely decode a recieved metadata (stat) structure |
346 | * @v9ses: session info | ||
347 | * @bufp: buffer to deserialize | 344 | * @bufp: buffer to deserialize |
348 | * @stat: metadata (stat) structure | 345 | * @stat: metadata (stat) structure |
349 | * @dbufp: buffer to deserialize variable strings into | 346 | * @dbufp: buffer to deserialize variable strings into |
347 | * @extended: non-zero if 9P2000.u | ||
350 | * | 348 | * |
351 | */ | 349 | */ |
352 | 350 | ||
353 | static inline int | 351 | static inline int |
354 | deserialize_stat(struct v9fs_session_info *v9ses, struct cbuf *bufp, | 352 | deserialize_stat(struct cbuf *bufp, struct v9fs_stat *stat, |
355 | struct v9fs_stat *stat, struct cbuf *dbufp) | 353 | struct cbuf *dbufp, int extended) |
356 | { | 354 | { |
357 | 355 | ||
358 | stat->size = buf_get_int16(bufp); | 356 | stat->size = buf_get_int16(bufp); |
@@ -370,7 +368,7 @@ deserialize_stat(struct v9fs_session_info *v9ses, struct cbuf *bufp, | |||
370 | stat->gid = buf_get_stringb(bufp, dbufp); | 368 | stat->gid = buf_get_stringb(bufp, dbufp); |
371 | stat->muid = buf_get_stringb(bufp, dbufp); | 369 | stat->muid = buf_get_stringb(bufp, dbufp); |
372 | 370 | ||
373 | if (v9ses->extended) { | 371 | if (extended) { |
374 | stat->extension = buf_get_stringb(bufp, dbufp); | 372 | stat->extension = buf_get_stringb(bufp, dbufp); |
375 | stat->n_uid = buf_get_int32(bufp); | 373 | stat->n_uid = buf_get_int32(bufp); |
376 | stat->n_gid = buf_get_int32(bufp); | 374 | stat->n_gid = buf_get_int32(bufp); |
@@ -385,20 +383,20 @@ deserialize_stat(struct v9fs_session_info *v9ses, struct cbuf *bufp, | |||
385 | 383 | ||
386 | /** | 384 | /** |
387 | * deserialize_statb - wrapper for decoding a received metadata structure | 385 | * deserialize_statb - wrapper for decoding a received metadata structure |
388 | * @v9ses: session info | ||
389 | * @bufp: buffer to deserialize | 386 | * @bufp: buffer to deserialize |
390 | * @dbufp: buffer to deserialize variable strings into | 387 | * @dbufp: buffer to deserialize variable strings into |
388 | * @extended: non-zero if 9P2000.u | ||
391 | * | 389 | * |
392 | */ | 390 | */ |
393 | 391 | ||
394 | static inline struct v9fs_stat *deserialize_statb(struct v9fs_session_info | 392 | static inline struct v9fs_stat *deserialize_statb(struct cbuf *bufp, |
395 | *v9ses, struct cbuf *bufp, | 393 | struct cbuf *dbufp, |
396 | struct cbuf *dbufp) | 394 | int extended) |
397 | { | 395 | { |
398 | struct v9fs_stat *ret = buf_alloc(dbufp, sizeof(struct v9fs_stat)); | 396 | struct v9fs_stat *ret = buf_alloc(dbufp, sizeof(struct v9fs_stat)); |
399 | 397 | ||
400 | if (ret) { | 398 | if (ret) { |
401 | int n = deserialize_stat(v9ses, bufp, ret, dbufp); | 399 | int n = deserialize_stat(bufp, ret, dbufp, extended); |
402 | if (n <= 0) | 400 | if (n <= 0) |
403 | return NULL; | 401 | return NULL; |
404 | } | 402 | } |
@@ -408,17 +406,16 @@ static inline struct v9fs_stat *deserialize_statb(struct v9fs_session_info | |||
408 | 406 | ||
409 | /** | 407 | /** |
410 | * v9fs_deserialize_stat - decode a received metadata structure | 408 | * v9fs_deserialize_stat - decode a received metadata structure |
411 | * @v9ses: session info | ||
412 | * @buf: buffer to deserialize | 409 | * @buf: buffer to deserialize |
413 | * @buflen: length of received buffer | 410 | * @buflen: length of received buffer |
414 | * @stat: metadata structure to decode into | 411 | * @stat: metadata structure to decode into |
415 | * @statlen: length of destination metadata structure | 412 | * @statlen: length of destination metadata structure |
413 | * @extended: non-zero if 9P2000.u | ||
416 | * | 414 | * |
417 | */ | 415 | */ |
418 | 416 | ||
419 | int | 417 | int v9fs_deserialize_stat(void *buf, u32 buflen, struct v9fs_stat *stat, |
420 | v9fs_deserialize_stat(struct v9fs_session_info *v9ses, void *buf, | 418 | u32 statlen, int extended) |
421 | u32 buflen, struct v9fs_stat *stat, u32 statlen) | ||
422 | { | 419 | { |
423 | struct cbuf buffer; | 420 | struct cbuf buffer; |
424 | struct cbuf *bufp = &buffer; | 421 | struct cbuf *bufp = &buffer; |
@@ -429,11 +426,10 @@ v9fs_deserialize_stat(struct v9fs_session_info *v9ses, void *buf, | |||
429 | buf_init(dbufp, (char *)stat + sizeof(struct v9fs_stat), | 426 | buf_init(dbufp, (char *)stat + sizeof(struct v9fs_stat), |
430 | statlen - sizeof(struct v9fs_stat)); | 427 | statlen - sizeof(struct v9fs_stat)); |
431 | 428 | ||
432 | return deserialize_stat(v9ses, bufp, stat, dbufp); | 429 | return deserialize_stat(bufp, stat, dbufp, extended); |
433 | } | 430 | } |
434 | 431 | ||
435 | static inline int | 432 | static inline int v9fs_size_fcall(struct v9fs_fcall *fcall, int extended) |
436 | v9fs_size_fcall(struct v9fs_session_info *v9ses, struct v9fs_fcall *fcall) | ||
437 | { | 433 | { |
438 | int size = 4 + 1 + 2; /* size[4] msg[1] tag[2] */ | 434 | int size = 4 + 1 + 2; /* size[4] msg[1] tag[2] */ |
439 | int i = 0; | 435 | int i = 0; |
@@ -485,7 +481,7 @@ v9fs_size_fcall(struct v9fs_session_info *v9ses, struct v9fs_fcall *fcall) | |||
485 | break; | 481 | break; |
486 | case TWSTAT: /* fid[4] stat[n] */ | 482 | case TWSTAT: /* fid[4] stat[n] */ |
487 | fcall->params.twstat.stat->size = | 483 | fcall->params.twstat.stat->size = |
488 | v9fs_size_stat(v9ses, fcall->params.twstat.stat); | 484 | v9fs_size_stat(fcall->params.twstat.stat, extended); |
489 | size += 4 + 2 + 2 + fcall->params.twstat.stat->size; | 485 | size += 4 + 2 + 2 + fcall->params.twstat.stat->size; |
490 | } | 486 | } |
491 | return size; | 487 | return size; |
@@ -493,16 +489,16 @@ v9fs_size_fcall(struct v9fs_session_info *v9ses, struct v9fs_fcall *fcall) | |||
493 | 489 | ||
494 | /* | 490 | /* |
495 | * v9fs_serialize_fcall - marshall fcall struct into a packet | 491 | * v9fs_serialize_fcall - marshall fcall struct into a packet |
496 | * @v9ses: session information | ||
497 | * @fcall: structure to convert | 492 | * @fcall: structure to convert |
498 | * @data: buffer to serialize fcall into | 493 | * @data: buffer to serialize fcall into |
499 | * @datalen: length of buffer to serialize fcall into | 494 | * @datalen: length of buffer to serialize fcall into |
495 | * @extended: non-zero if 9P2000.u | ||
500 | * | 496 | * |
501 | */ | 497 | */ |
502 | 498 | ||
503 | int | 499 | int |
504 | v9fs_serialize_fcall(struct v9fs_session_info *v9ses, struct v9fs_fcall *fcall, | 500 | v9fs_serialize_fcall(struct v9fs_fcall *fcall, void *data, u32 datalen, |
505 | void *data, u32 datalen) | 501 | int extended) |
506 | { | 502 | { |
507 | int i = 0; | 503 | int i = 0; |
508 | struct v9fs_stat *stat = NULL; | 504 | struct v9fs_stat *stat = NULL; |
@@ -516,7 +512,7 @@ v9fs_serialize_fcall(struct v9fs_session_info *v9ses, struct v9fs_fcall *fcall, | |||
516 | return -EINVAL; | 512 | return -EINVAL; |
517 | } | 513 | } |
518 | 514 | ||
519 | fcall->size = v9fs_size_fcall(v9ses, fcall); | 515 | fcall->size = v9fs_size_fcall(fcall, extended); |
520 | 516 | ||
521 | buf_put_int32(bufp, fcall->size); | 517 | buf_put_int32(bufp, fcall->size); |
522 | buf_put_int8(bufp, fcall->id); | 518 | buf_put_int8(bufp, fcall->id); |
@@ -591,31 +587,31 @@ v9fs_serialize_fcall(struct v9fs_session_info *v9ses, struct v9fs_fcall *fcall, | |||
591 | stat = fcall->params.twstat.stat; | 587 | stat = fcall->params.twstat.stat; |
592 | 588 | ||
593 | buf_put_int16(bufp, stat->size + 2); | 589 | buf_put_int16(bufp, stat->size + 2); |
594 | serialize_stat(v9ses, stat, bufp); | 590 | serialize_stat(stat, bufp, extended); |
595 | break; | 591 | break; |
596 | } | 592 | } |
597 | 593 | ||
598 | if (buf_check_overflow(bufp)) | 594 | if (buf_check_overflow(bufp)) { |
595 | dprintk(DEBUG_ERROR, "buffer overflow\n"); | ||
599 | return -EIO; | 596 | return -EIO; |
597 | } | ||
600 | 598 | ||
601 | return fcall->size; | 599 | return fcall->size; |
602 | } | 600 | } |
603 | 601 | ||
604 | /** | 602 | /** |
605 | * deserialize_fcall - unmarshal a response | 603 | * deserialize_fcall - unmarshal a response |
606 | * @v9ses: session information | ||
607 | * @msgsize: size of rcall message | ||
608 | * @buf: recieved buffer | 604 | * @buf: recieved buffer |
609 | * @buflen: length of received buffer | 605 | * @buflen: length of received buffer |
610 | * @rcall: fcall structure to populate | 606 | * @rcall: fcall structure to populate |
611 | * @rcalllen: length of fcall structure to populate | 607 | * @rcalllen: length of fcall structure to populate |
608 | * @extended: non-zero if 9P2000.u | ||
612 | * | 609 | * |
613 | */ | 610 | */ |
614 | 611 | ||
615 | int | 612 | int |
616 | v9fs_deserialize_fcall(struct v9fs_session_info *v9ses, u32 msgsize, | 613 | v9fs_deserialize_fcall(void *buf, u32 buflen, struct v9fs_fcall *rcall, |
617 | void *buf, u32 buflen, struct v9fs_fcall *rcall, | 614 | int rcalllen, int extended) |
618 | int rcalllen) | ||
619 | { | 615 | { |
620 | 616 | ||
621 | struct cbuf buffer; | 617 | struct cbuf buffer; |
@@ -628,7 +624,7 @@ v9fs_deserialize_fcall(struct v9fs_session_info *v9ses, u32 msgsize, | |||
628 | buf_init(dbufp, (char *)rcall + sizeof(struct v9fs_fcall), | 624 | buf_init(dbufp, (char *)rcall + sizeof(struct v9fs_fcall), |
629 | rcalllen - sizeof(struct v9fs_fcall)); | 625 | rcalllen - sizeof(struct v9fs_fcall)); |
630 | 626 | ||
631 | rcall->size = msgsize; | 627 | rcall->size = buf_get_int32(bufp); |
632 | rcall->id = buf_get_int8(bufp); | 628 | rcall->id = buf_get_int8(bufp); |
633 | rcall->tag = buf_get_int16(bufp); | 629 | rcall->tag = buf_get_int16(bufp); |
634 | 630 | ||
@@ -651,6 +647,12 @@ v9fs_deserialize_fcall(struct v9fs_session_info *v9ses, u32 msgsize, | |||
651 | break; | 647 | break; |
652 | case RWALK: | 648 | case RWALK: |
653 | rcall->params.rwalk.nwqid = buf_get_int16(bufp); | 649 | rcall->params.rwalk.nwqid = buf_get_int16(bufp); |
650 | if (rcall->params.rwalk.nwqid > 16) { | ||
651 | eprintk(KERN_ERR, "Rwalk with more than 16 qids: %d\n", | ||
652 | rcall->params.rwalk.nwqid); | ||
653 | return -EPROTO; | ||
654 | } | ||
655 | |||
654 | rcall->params.rwalk.wqids = buf_alloc(dbufp, | 656 | rcall->params.rwalk.wqids = buf_alloc(dbufp, |
655 | rcall->params.rwalk.nwqid * sizeof(struct v9fs_qid)); | 657 | rcall->params.rwalk.nwqid * sizeof(struct v9fs_qid)); |
656 | if (rcall->params.rwalk.wqids) | 658 | if (rcall->params.rwalk.wqids) |
@@ -690,19 +692,21 @@ v9fs_deserialize_fcall(struct v9fs_session_info *v9ses, u32 msgsize, | |||
690 | case RSTAT: | 692 | case RSTAT: |
691 | buf_get_int16(bufp); | 693 | buf_get_int16(bufp); |
692 | rcall->params.rstat.stat = | 694 | rcall->params.rstat.stat = |
693 | deserialize_statb(v9ses, bufp, dbufp); | 695 | deserialize_statb(bufp, dbufp, extended); |
694 | break; | 696 | break; |
695 | case RWSTAT: | 697 | case RWSTAT: |
696 | break; | 698 | break; |
697 | case RERROR: | 699 | case RERROR: |
698 | rcall->params.rerror.error = buf_get_stringb(bufp, dbufp); | 700 | rcall->params.rerror.error = buf_get_stringb(bufp, dbufp); |
699 | if (v9ses->extended) | 701 | if (extended) |
700 | rcall->params.rerror.errno = buf_get_int16(bufp); | 702 | rcall->params.rerror.errno = buf_get_int16(bufp); |
701 | break; | 703 | break; |
702 | } | 704 | } |
703 | 705 | ||
704 | if (buf_check_overflow(bufp) || buf_check_overflow(dbufp)) | 706 | if (buf_check_overflow(bufp) || buf_check_overflow(dbufp)) { |
707 | dprintk(DEBUG_ERROR, "buffer overflow\n"); | ||
705 | return -EIO; | 708 | return -EIO; |
709 | } | ||
706 | 710 | ||
707 | return rcall->size; | 711 | return rcall->size; |
708 | } | 712 | } |