qemu-nbd: introduce NBDExport
Wrap the common parameters of nbd_trip and nbd_negotiate in a single opaque struct. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
		
							parent
							
								
									a030b347aa
								
							
						
					
					
						commit
						af49bbbe78
					
				
							
								
								
									
										64
									
								
								nbd.c
								
								
								
								
							
							
						
						
									
										64
									
								
								nbd.c
								
								
								
								
							| 
						 | 
				
			
			@ -18,6 +18,7 @@
 | 
			
		|||
 | 
			
		||||
#include "nbd.h"
 | 
			
		||||
#include "block.h"
 | 
			
		||||
#include "block_int.h"
 | 
			
		||||
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
| 
						 | 
				
			
			@ -186,7 +187,7 @@ int unix_socket_outgoing(const char *path)
 | 
			
		|||
                  Request (type == 2)
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
int nbd_negotiate(int csock, off_t size, uint32_t flags)
 | 
			
		||||
static int nbd_send_negotiate(int csock, off_t size, uint32_t flags)
 | 
			
		||||
{
 | 
			
		||||
    char buf[8 + 8 + 8 + 128];
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -583,6 +584,33 @@ static int nbd_send_reply(int csock, struct nbd_reply *reply)
 | 
			
		|||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct NBDExport {
 | 
			
		||||
    BlockDriverState *bs;
 | 
			
		||||
    off_t dev_offset;
 | 
			
		||||
    off_t size;
 | 
			
		||||
    uint8_t *data;
 | 
			
		||||
    uint32_t nbdflags;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
NBDExport *nbd_export_new(BlockDriverState *bs, off_t dev_offset,
 | 
			
		||||
                          off_t size, uint32_t nbdflags)
 | 
			
		||||
{
 | 
			
		||||
    NBDExport *exp = g_malloc0(sizeof(NBDExport));
 | 
			
		||||
    exp->bs = bs;
 | 
			
		||||
    exp->dev_offset = dev_offset;
 | 
			
		||||
    exp->nbdflags = nbdflags;
 | 
			
		||||
    exp->size = size == -1 ? exp->bs->total_sectors * 512 : size;
 | 
			
		||||
    exp->data = qemu_blockalign(exp->bs, NBD_BUFFER_SIZE);
 | 
			
		||||
    return exp;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void nbd_export_close(NBDExport *exp)
 | 
			
		||||
{
 | 
			
		||||
    qemu_vfree(exp->data);
 | 
			
		||||
    bdrv_close(exp->bs);
 | 
			
		||||
    g_free(exp);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int nbd_do_send_reply(int csock, struct nbd_reply *reply,
 | 
			
		||||
                             uint8_t *data, int len)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -652,9 +680,7 @@ out:
 | 
			
		|||
    return rc;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int nbd_trip(BlockDriverState *bs, int csock, off_t size,
 | 
			
		||||
             uint64_t dev_offset, uint32_t nbdflags,
 | 
			
		||||
             uint8_t *data)
 | 
			
		||||
int nbd_trip(NBDExport *exp, int csock)
 | 
			
		||||
{
 | 
			
		||||
    struct nbd_request request;
 | 
			
		||||
    struct nbd_reply reply;
 | 
			
		||||
| 
						 | 
				
			
			@ -662,7 +688,7 @@ int nbd_trip(BlockDriverState *bs, int csock, off_t size,
 | 
			
		|||
 | 
			
		||||
    TRACE("Reading request.");
 | 
			
		||||
 | 
			
		||||
    ret = nbd_do_receive_request(csock, &request, data);
 | 
			
		||||
    ret = nbd_do_receive_request(csock, &request, exp->data);
 | 
			
		||||
    if (ret == -EIO) {
 | 
			
		||||
        return -1;
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -675,10 +701,11 @@ int nbd_trip(BlockDriverState *bs, int csock, off_t size,
 | 
			
		|||
        goto error_reply;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if ((request.from + request.len) > size) {
 | 
			
		||||
    if ((request.from + request.len) > exp->size) {
 | 
			
		||||
            LOG("From: %" PRIu64 ", Len: %u, Size: %" PRIu64
 | 
			
		||||
            ", Offset: %" PRIu64 "\n",
 | 
			
		||||
                    request.from, request.len, (uint64_t)size, dev_offset);
 | 
			
		||||
                    request.from, request.len,
 | 
			
		||||
                    (uint64_t)exp->size, exp->dev_offset);
 | 
			
		||||
        LOG("requested operation past EOF--bad client?");
 | 
			
		||||
        goto invalid_request;
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -687,8 +714,8 @@ int nbd_trip(BlockDriverState *bs, int csock, off_t size,
 | 
			
		|||
    case NBD_CMD_READ:
 | 
			
		||||
        TRACE("Request type is READ");
 | 
			
		||||
 | 
			
		||||
        ret = bdrv_read(bs, (request.from + dev_offset) / 512,
 | 
			
		||||
                        data, request.len / 512);
 | 
			
		||||
        ret = bdrv_read(exp->bs, (request.from + exp->dev_offset) / 512,
 | 
			
		||||
                        exp->data, request.len / 512);
 | 
			
		||||
        if (ret < 0) {
 | 
			
		||||
            LOG("reading from file failed");
 | 
			
		||||
            reply.error = -ret;
 | 
			
		||||
| 
						 | 
				
			
			@ -696,13 +723,13 @@ int nbd_trip(BlockDriverState *bs, int csock, off_t size,
 | 
			
		|||
        }
 | 
			
		||||
 | 
			
		||||
        TRACE("Read %u byte(s)", request.len);
 | 
			
		||||
        if (nbd_do_send_reply(csock, &reply, data, request.len) < 0)
 | 
			
		||||
        if (nbd_do_send_reply(csock, &reply, exp->data, request.len) < 0)
 | 
			
		||||
            return -1;
 | 
			
		||||
        break;
 | 
			
		||||
    case NBD_CMD_WRITE:
 | 
			
		||||
        TRACE("Request type is WRITE");
 | 
			
		||||
 | 
			
		||||
        if (nbdflags & NBD_FLAG_READ_ONLY) {
 | 
			
		||||
        if (exp->nbdflags & NBD_FLAG_READ_ONLY) {
 | 
			
		||||
            TRACE("Server is read-only, return error");
 | 
			
		||||
            reply.error = EROFS;
 | 
			
		||||
            goto error_reply;
 | 
			
		||||
| 
						 | 
				
			
			@ -710,8 +737,8 @@ int nbd_trip(BlockDriverState *bs, int csock, off_t size,
 | 
			
		|||
 | 
			
		||||
        TRACE("Writing to device");
 | 
			
		||||
 | 
			
		||||
        ret = bdrv_write(bs, (request.from + dev_offset) / 512,
 | 
			
		||||
                         data, request.len / 512);
 | 
			
		||||
        ret = bdrv_write(exp->bs, (request.from + exp->dev_offset) / 512,
 | 
			
		||||
                         exp->data, request.len / 512);
 | 
			
		||||
        if (ret < 0) {
 | 
			
		||||
            LOG("writing to file failed");
 | 
			
		||||
            reply.error = -ret;
 | 
			
		||||
| 
						 | 
				
			
			@ -719,7 +746,7 @@ int nbd_trip(BlockDriverState *bs, int csock, off_t size,
 | 
			
		|||
        }
 | 
			
		||||
 | 
			
		||||
        if (request.type & NBD_CMD_FLAG_FUA) {
 | 
			
		||||
            ret = bdrv_flush(bs);
 | 
			
		||||
            ret = bdrv_flush(exp->bs);
 | 
			
		||||
            if (ret < 0) {
 | 
			
		||||
                LOG("flush failed");
 | 
			
		||||
                reply.error = -ret;
 | 
			
		||||
| 
						 | 
				
			
			@ -737,7 +764,7 @@ int nbd_trip(BlockDriverState *bs, int csock, off_t size,
 | 
			
		|||
    case NBD_CMD_FLUSH:
 | 
			
		||||
        TRACE("Request type is FLUSH");
 | 
			
		||||
 | 
			
		||||
        ret = bdrv_flush(bs);
 | 
			
		||||
        ret = bdrv_flush(exp->bs);
 | 
			
		||||
        if (ret < 0) {
 | 
			
		||||
            LOG("flush failed");
 | 
			
		||||
            reply.error = -ret;
 | 
			
		||||
| 
						 | 
				
			
			@ -748,7 +775,7 @@ int nbd_trip(BlockDriverState *bs, int csock, off_t size,
 | 
			
		|||
        break;
 | 
			
		||||
    case NBD_CMD_TRIM:
 | 
			
		||||
        TRACE("Request type is TRIM");
 | 
			
		||||
        ret = bdrv_discard(bs, (request.from + dev_offset) / 512,
 | 
			
		||||
        ret = bdrv_discard(exp->bs, (request.from + exp->dev_offset) / 512,
 | 
			
		||||
                           request.len / 512);
 | 
			
		||||
        if (ret < 0) {
 | 
			
		||||
            LOG("discard failed");
 | 
			
		||||
| 
						 | 
				
			
			@ -771,3 +798,8 @@ int nbd_trip(BlockDriverState *bs, int csock, off_t size,
 | 
			
		|||
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int nbd_negotiate(NBDExport *exp, int csock)
 | 
			
		||||
{
 | 
			
		||||
    return nbd_send_negotiate(csock, exp->size, exp->nbdflags);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										11
									
								
								nbd.h
								
								
								
								
							
							
						
						
									
										11
									
								
								nbd.h
								
								
								
								
							| 
						 | 
				
			
			@ -67,15 +67,20 @@ int tcp_socket_incoming_spec(const char *address_and_port);
 | 
			
		|||
int unix_socket_outgoing(const char *path);
 | 
			
		||||
int unix_socket_incoming(const char *path);
 | 
			
		||||
 | 
			
		||||
int nbd_negotiate(int csock, off_t size, uint32_t flags);
 | 
			
		||||
int nbd_receive_negotiate(int csock, const char *name, uint32_t *flags,
 | 
			
		||||
                          off_t *size, size_t *blocksize);
 | 
			
		||||
int nbd_init(int fd, int csock, uint32_t flags, off_t size, size_t blocksize);
 | 
			
		||||
int nbd_send_request(int csock, struct nbd_request *request);
 | 
			
		||||
int nbd_receive_reply(int csock, struct nbd_reply *reply);
 | 
			
		||||
int nbd_trip(BlockDriverState *bs, int csock, off_t size, uint64_t dev_offset,
 | 
			
		||||
             uint32_t nbdflags, uint8_t *data);
 | 
			
		||||
int nbd_client(int fd);
 | 
			
		||||
int nbd_disconnect(int fd);
 | 
			
		||||
 | 
			
		||||
typedef struct NBDExport NBDExport;
 | 
			
		||||
 | 
			
		||||
NBDExport *nbd_export_new(BlockDriverState *bs, off_t dev_offset,
 | 
			
		||||
                          off_t size, uint32_t nbdflags);
 | 
			
		||||
void nbd_export_close(NBDExport *exp);
 | 
			
		||||
int nbd_negotiate(NBDExport *exp, int csock);
 | 
			
		||||
int nbd_trip(NBDExport *exp, int csock);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										15
									
								
								qemu-nbd.c
								
								
								
								
							
							
						
						
									
										15
									
								
								qemu-nbd.c
								
								
								
								
							| 
						 | 
				
			
			@ -36,6 +36,7 @@
 | 
			
		|||
#define SOCKET_PATH    "/var/lock/qemu-nbd-%s"
 | 
			
		||||
 | 
			
		||||
static int sigterm_wfd;
 | 
			
		||||
static NBDExport *exp;
 | 
			
		||||
static int verbose;
 | 
			
		||||
static char *device;
 | 
			
		||||
static char *srcpath;
 | 
			
		||||
| 
						 | 
				
			
			@ -280,7 +281,6 @@ int main(int argc, char **argv)
 | 
			
		|||
    int partition = -1;
 | 
			
		||||
    int ret;
 | 
			
		||||
    int shared = 1;
 | 
			
		||||
    uint8_t *data;
 | 
			
		||||
    fd_set fds;
 | 
			
		||||
    int *sharing_fds;
 | 
			
		||||
    int fd;
 | 
			
		||||
| 
						 | 
				
			
			@ -489,6 +489,7 @@ int main(int argc, char **argv)
 | 
			
		|||
        err(EXIT_FAILURE, "Could not find partition %d", partition);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    exp = nbd_export_new(bs, dev_offset, fd_size, nbdflags);
 | 
			
		||||
    sharing_fds = g_malloc((shared + 1) * sizeof(int));
 | 
			
		||||
 | 
			
		||||
    if (sockpath) {
 | 
			
		||||
| 
						 | 
				
			
			@ -516,11 +517,6 @@ int main(int argc, char **argv)
 | 
			
		|||
    max_fd = sharing_fds[0];
 | 
			
		||||
    nb_fds++;
 | 
			
		||||
 | 
			
		||||
    data = qemu_blockalign(bs, NBD_BUFFER_SIZE);
 | 
			
		||||
    if (data == NULL) {
 | 
			
		||||
        errx(EXIT_FAILURE, "Cannot allocate data buffer");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    do {
 | 
			
		||||
        FD_ZERO(&fds);
 | 
			
		||||
        FD_SET(sigterm_fd[0], &fds);
 | 
			
		||||
| 
						 | 
				
			
			@ -538,8 +534,7 @@ int main(int argc, char **argv)
 | 
			
		|||
            ret--;
 | 
			
		||||
        for (i = 1; i < nb_fds && ret; i++) {
 | 
			
		||||
            if (FD_ISSET(sharing_fds[i], &fds)) {
 | 
			
		||||
                if (nbd_trip(bs, sharing_fds[i], fd_size, dev_offset,
 | 
			
		||||
                             nbdflags, data) != 0) {
 | 
			
		||||
                if (nbd_trip(exp, sharing_fds[i]) != 0) {
 | 
			
		||||
                    close(sharing_fds[i]);
 | 
			
		||||
                    nb_fds--;
 | 
			
		||||
                    sharing_fds[i] = sharing_fds[nb_fds];
 | 
			
		||||
| 
						 | 
				
			
			@ -555,7 +550,7 @@ int main(int argc, char **argv)
 | 
			
		|||
                                             (struct sockaddr *)&addr,
 | 
			
		||||
                                             &addr_len);
 | 
			
		||||
                if (sharing_fds[nb_fds] != -1 &&
 | 
			
		||||
                    nbd_negotiate(sharing_fds[nb_fds], fd_size, nbdflags) != -1) {
 | 
			
		||||
                    nbd_negotiate(exp, sharing_fds[nb_fds]) != -1) {
 | 
			
		||||
                        if (sharing_fds[nb_fds] > max_fd)
 | 
			
		||||
                            max_fd = sharing_fds[nb_fds];
 | 
			
		||||
                        nb_fds++;
 | 
			
		||||
| 
						 | 
				
			
			@ -563,9 +558,9 @@ int main(int argc, char **argv)
 | 
			
		|||
            }
 | 
			
		||||
        }
 | 
			
		||||
    } while (persistent || nb_fds > 1);
 | 
			
		||||
    qemu_vfree(data);
 | 
			
		||||
 | 
			
		||||
    close(sharing_fds[0]);
 | 
			
		||||
    nbd_export_close(exp);
 | 
			
		||||
    g_free(sharing_fds);
 | 
			
		||||
    if (sockpath) {
 | 
			
		||||
        unlink(sockpath);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue