Skip to content

Commit

Permalink
qemu-nbd: introduce NBDExport
Browse files Browse the repository at this point in the history
Wrap the common parameters of nbd_trip and nbd_negotiate in a
single opaque struct.

Signed-off-by: Paolo Bonzini <[email protected]>
  • Loading branch information
bonzini committed Dec 22, 2011
1 parent a030b34 commit af49bbb
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 29 deletions.
64 changes: 48 additions & 16 deletions nbd.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

#include "nbd.h"
#include "block.h"
#include "block_int.h"

#include <errno.h>
#include <string.h>
Expand Down Expand Up @@ -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];

Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -652,17 +680,15 @@ static int nbd_do_receive_request(int csock, struct nbd_request *request,
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;
int ret;

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;
}
Expand All @@ -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;
}
Expand All @@ -687,39 +714,39 @@ 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;
goto error_reply;
}

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;
}

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;
goto error_reply;
}

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;
Expand All @@ -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;
Expand All @@ -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");
Expand All @@ -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 changes: 8 additions & 3 deletions nbd.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 changes: 5 additions & 10 deletions qemu-nbd.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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);
Expand All @@ -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];
Expand All @@ -555,17 +550,17 @@ 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++;
}
}
}
} while (persistent || nb_fds > 1);
qemu_vfree(data);

close(sharing_fds[0]);
nbd_export_close(exp);
g_free(sharing_fds);
if (sockpath) {
unlink(sockpath);
Expand Down

0 comments on commit af49bbb

Please sign in to comment.