0

I'm new to iSCSI protocol and I have a task to catch and interpret the commands between QEMU and iSCSI server when a VM is boot from iSCSI drive.

I setup tgtd on Ubuntu and managed to install a guest OS into a disk image created by qemu-img with a format of raw, which is the backing storage of tgtd.

To achieve my target, I decided to write a transparent layer between QEMU and tgtd, which performs as a server for QEMU and a client for tgtd. After a brief reading of RFC3720, I wrote my transparent layer with the core code as

    while(1) {
        rt_val = recv(server_conn_sock, BHS, 48, 0);
        unsigned int TotalAHSLength = (unsigned int)BHS[4];
        unsigned int DataSegmentLength = ((unsigned int)BHS[5] << 16) | ((unsigned int)BHS[6] << 8) | (unsigned int)BHS[7];
        unsigned int DataSegmentLengthWithPadding = DataSegmentLength % 4 ? DataSegmentLength + 4 - (DataSegmentLength % 4) : DataSegmentLength;
        if(TotalAHSLength > 0) {
            rt_val = recv(server_conn_sock, AHS, 4 * TotalAHSLength, 0);
        }
        if(DataSegmentLengthWithPadding > 0) {
            rt_val = recv(server_conn_sock, DataSegment, DataSegmentLengthWithPadding, 0);
        }
        rt_val = send(client_sock, BHS, 48, 0);
        if(TotalAHSLength > 0) {
            rt_val = send(client_sock, AHS, 4 * TotalAHSLength, 0);
        }
        if(DataSegmentLengthWithPadding > 0) {
            rt_val = send(client_sock, DataSegment, DataSegmentLengthWithPadding, 0);
        }
    
        rt_val = recv(client_sock, BHS, 48, 0);
        TotalAHSLength = (unsigned int)BHS[4];
        DataSegmentLength = ((unsigned int)BHS[5] << 16) | ((unsigned int)BHS[6] << 8) | (unsigned int)BHS[7];
        DataSegmentLengthWithPadding = DataSegmentLength % 4 ? DataSegmentLength + 4 - (DataSegmentLength % 4) : DataSegmentLength;
        if(TotalAHSLength > 0) {
            rt_val = recv(client_sock, AHS, 4 * TotalAHSLength, 0);
        }
        if(DataSegmentLengthWithPadding > 0) {
            rt_val = recv(client_sock, DataSegment, DataSegmentLengthWithPadding, 0);
        }
        send(server_conn_sock, BHS, 48, 0);
        if(TotalAHSLength > 0) {
            send(server_conn_sock, AHS, 4 * TotalAHSLength, 0);
        }
        if(DataSegmentLengthWithPadding > 0) {
            send(server_conn_sock, DataSegment, DataSegmentLengthWithPadding, 0);
        }
    }

The code is basically forwarding everything between QEMU and tgtd. However, I found that the speed of QEMU to boot the guest OS is more than 100 times slower compared with booting with a direct connection to tgtd. My task required my intermediate layer not to affect the performance of QEMU.

So, what could be a possible reason for the difference in speed of reading disk?

citrate
  • 189
  • 1
  • 1
  • 8

0 Answers0