Revision af49bbbe nbd.c
b/nbd.c | ||
---|---|---|
18 | 18 |
|
19 | 19 |
#include "nbd.h" |
20 | 20 |
#include "block.h" |
21 |
#include "block_int.h" |
|
21 | 22 |
|
22 | 23 |
#include <errno.h> |
23 | 24 |
#include <string.h> |
... | ... | |
186 | 187 |
Request (type == 2) |
187 | 188 |
*/ |
188 | 189 |
|
189 |
int nbd_negotiate(int csock, off_t size, uint32_t flags)
|
|
190 |
static int nbd_send_negotiate(int csock, off_t size, uint32_t flags)
|
|
190 | 191 |
{ |
191 | 192 |
char buf[8 + 8 + 8 + 128]; |
192 | 193 |
|
... | ... | |
583 | 584 |
return 0; |
584 | 585 |
} |
585 | 586 |
|
587 |
struct NBDExport { |
|
588 |
BlockDriverState *bs; |
|
589 |
off_t dev_offset; |
|
590 |
off_t size; |
|
591 |
uint8_t *data; |
|
592 |
uint32_t nbdflags; |
|
593 |
}; |
|
594 |
|
|
595 |
NBDExport *nbd_export_new(BlockDriverState *bs, off_t dev_offset, |
|
596 |
off_t size, uint32_t nbdflags) |
|
597 |
{ |
|
598 |
NBDExport *exp = g_malloc0(sizeof(NBDExport)); |
|
599 |
exp->bs = bs; |
|
600 |
exp->dev_offset = dev_offset; |
|
601 |
exp->nbdflags = nbdflags; |
|
602 |
exp->size = size == -1 ? exp->bs->total_sectors * 512 : size; |
|
603 |
exp->data = qemu_blockalign(exp->bs, NBD_BUFFER_SIZE); |
|
604 |
return exp; |
|
605 |
} |
|
606 |
|
|
607 |
void nbd_export_close(NBDExport *exp) |
|
608 |
{ |
|
609 |
qemu_vfree(exp->data); |
|
610 |
bdrv_close(exp->bs); |
|
611 |
g_free(exp); |
|
612 |
} |
|
613 |
|
|
586 | 614 |
static int nbd_do_send_reply(int csock, struct nbd_reply *reply, |
587 | 615 |
uint8_t *data, int len) |
588 | 616 |
{ |
... | ... | |
652 | 680 |
return rc; |
653 | 681 |
} |
654 | 682 |
|
655 |
int nbd_trip(BlockDriverState *bs, int csock, off_t size, |
|
656 |
uint64_t dev_offset, uint32_t nbdflags, |
|
657 |
uint8_t *data) |
|
683 |
int nbd_trip(NBDExport *exp, int csock) |
|
658 | 684 |
{ |
659 | 685 |
struct nbd_request request; |
660 | 686 |
struct nbd_reply reply; |
... | ... | |
662 | 688 |
|
663 | 689 |
TRACE("Reading request."); |
664 | 690 |
|
665 |
ret = nbd_do_receive_request(csock, &request, data); |
|
691 |
ret = nbd_do_receive_request(csock, &request, exp->data);
|
|
666 | 692 |
if (ret == -EIO) { |
667 | 693 |
return -1; |
668 | 694 |
} |
... | ... | |
675 | 701 |
goto error_reply; |
676 | 702 |
} |
677 | 703 |
|
678 |
if ((request.from + request.len) > size) { |
|
704 |
if ((request.from + request.len) > exp->size) {
|
|
679 | 705 |
LOG("From: %" PRIu64 ", Len: %u, Size: %" PRIu64 |
680 | 706 |
", Offset: %" PRIu64 "\n", |
681 |
request.from, request.len, (uint64_t)size, dev_offset); |
|
707 |
request.from, request.len, |
|
708 |
(uint64_t)exp->size, exp->dev_offset); |
|
682 | 709 |
LOG("requested operation past EOF--bad client?"); |
683 | 710 |
goto invalid_request; |
684 | 711 |
} |
... | ... | |
687 | 714 |
case NBD_CMD_READ: |
688 | 715 |
TRACE("Request type is READ"); |
689 | 716 |
|
690 |
ret = bdrv_read(bs, (request.from + dev_offset) / 512,
|
|
691 |
data, request.len / 512); |
|
717 |
ret = bdrv_read(exp->bs, (request.from + exp->dev_offset) / 512,
|
|
718 |
exp->data, request.len / 512);
|
|
692 | 719 |
if (ret < 0) { |
693 | 720 |
LOG("reading from file failed"); |
694 | 721 |
reply.error = -ret; |
... | ... | |
696 | 723 |
} |
697 | 724 |
|
698 | 725 |
TRACE("Read %u byte(s)", request.len); |
699 |
if (nbd_do_send_reply(csock, &reply, data, request.len) < 0) |
|
726 |
if (nbd_do_send_reply(csock, &reply, exp->data, request.len) < 0)
|
|
700 | 727 |
return -1; |
701 | 728 |
break; |
702 | 729 |
case NBD_CMD_WRITE: |
703 | 730 |
TRACE("Request type is WRITE"); |
704 | 731 |
|
705 |
if (nbdflags & NBD_FLAG_READ_ONLY) { |
|
732 |
if (exp->nbdflags & NBD_FLAG_READ_ONLY) {
|
|
706 | 733 |
TRACE("Server is read-only, return error"); |
707 | 734 |
reply.error = EROFS; |
708 | 735 |
goto error_reply; |
... | ... | |
710 | 737 |
|
711 | 738 |
TRACE("Writing to device"); |
712 | 739 |
|
713 |
ret = bdrv_write(bs, (request.from + dev_offset) / 512,
|
|
714 |
data, request.len / 512); |
|
740 |
ret = bdrv_write(exp->bs, (request.from + exp->dev_offset) / 512,
|
|
741 |
exp->data, request.len / 512);
|
|
715 | 742 |
if (ret < 0) { |
716 | 743 |
LOG("writing to file failed"); |
717 | 744 |
reply.error = -ret; |
... | ... | |
719 | 746 |
} |
720 | 747 |
|
721 | 748 |
if (request.type & NBD_CMD_FLAG_FUA) { |
722 |
ret = bdrv_flush(bs); |
|
749 |
ret = bdrv_flush(exp->bs);
|
|
723 | 750 |
if (ret < 0) { |
724 | 751 |
LOG("flush failed"); |
725 | 752 |
reply.error = -ret; |
... | ... | |
737 | 764 |
case NBD_CMD_FLUSH: |
738 | 765 |
TRACE("Request type is FLUSH"); |
739 | 766 |
|
740 |
ret = bdrv_flush(bs); |
|
767 |
ret = bdrv_flush(exp->bs);
|
|
741 | 768 |
if (ret < 0) { |
742 | 769 |
LOG("flush failed"); |
743 | 770 |
reply.error = -ret; |
... | ... | |
748 | 775 |
break; |
749 | 776 |
case NBD_CMD_TRIM: |
750 | 777 |
TRACE("Request type is TRIM"); |
751 |
ret = bdrv_discard(bs, (request.from + dev_offset) / 512,
|
|
778 |
ret = bdrv_discard(exp->bs, (request.from + exp->dev_offset) / 512,
|
|
752 | 779 |
request.len / 512); |
753 | 780 |
if (ret < 0) { |
754 | 781 |
LOG("discard failed"); |
... | ... | |
771 | 798 |
|
772 | 799 |
return 0; |
773 | 800 |
} |
801 |
|
|
802 |
int nbd_negotiate(NBDExport *exp, int csock) |
|
803 |
{ |
|
804 |
return nbd_send_negotiate(csock, exp->size, exp->nbdflags); |
|
805 |
} |
Also available in: Unified diff