%.o: %.c
$(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $<
+qemu-nbd-%.o: %.c
+ $(CC) $(CFLAGS) $(CPPFLAGS) -DQEMU_NBD -c -o $@ $<
+
qemu-nbd$(EXESUF): qemu-nbd.o nbd.o qemu-img-block.o \
- $(QEMU_IMG_BLOCK_OBJS)
+ osdep.o qemu-nbd-block-raw-posix.o $(BLOCK_OBJS)
$(CC) $(LDFLAGS) -o $@ $^ -lz $(LIBS)
# dyngen host tool
* THE SOFTWARE.
*/
#include "qemu-common.h"
-#ifndef QEMU_IMG
+#if !defined(QEMU_IMG) && !defined(QEMU_NBD)
#include "qemu-timer.h"
#include "exec-all.h"
#endif
//#define DEBUG_FLOPPY
//#define DEBUG_BLOCK
-#if defined(DEBUG_BLOCK) && !defined(QEMU_IMG)
+#if defined(DEBUG_BLOCK) && !defined(QEMU_IMG) && !defined(QEMU_NBD)
#define DEBUG_BLOCK_PRINT(formatCstr, args...) do { if (loglevel != 0) \
{ fprintf(logfile, formatCstr, ##args); fflush(logfile); } } while (0)
#else
static void aio_signal_handler(int signum)
{
-#ifndef QEMU_IMG
+#if !defined(QEMU_IMG) && !defined(QEMU_NBD)
CPUState *env = cpu_single_env;
if (env) {
/* stop the currently executing cpu because a timer occured */
sigset_t set;
int nb_sigs;
-#ifndef QEMU_IMG
+#if !defined(QEMU_IMG) && !defined(QEMU_NBD)
if (qemu_bh_poll())
return;
#endif
return acb;
}
-#ifndef QEMU_IMG
+#if !defined(QEMU_IMG) && !defined(QEMU_NBD)
static void raw_aio_em_cb(void* opaque)
{
RawAIOCB *acb = opaque;
* If O_DIRECT is used and the buffer is not aligned fall back
* to synchronous IO.
*/
-#if defined(O_DIRECT) && !defined(QEMU_IMG)
+#if defined(O_DIRECT) && !defined(QEMU_IMG) && !defined(QEMU_NBD)
BDRVRawState *s = bs->opaque;
if (unlikely(s->aligned_buf != NULL && ((uintptr_t) buf % 512))) {
* If O_DIRECT is used and the buffer is not aligned fall back
* to synchronous IO.
*/
-#if defined(O_DIRECT) && !defined(QEMU_IMG)
+#if defined(O_DIRECT) && !defined(QEMU_IMG) && !defined(QEMU_NBD)
BDRVRawState *s = bs->opaque;
if (unlikely(s->aligned_buf != NULL && ((uintptr_t) buf % 512))) {
return 0;
}
-#if defined(__linux__) && !defined(QEMU_IMG)
+#if defined(__linux__) && !defined(QEMU_IMG) && !defined(QEMU_NBD)
/* Note: we do not have a reliable method to detect if the floppy is
present. The current method is to try to open the floppy at every
return ret;
}
-int nbd_trip(BlockDriverState *bs, int csock, off_t size, uint64_t dev_offset, off_t *offset, bool readonly)
+int nbd_trip(BlockDriverState *bs, int csock, off_t size, uint64_t dev_offset,
+ off_t *offset, bool readonly, uint8_t *data, int data_size)
{
-#ifndef _REENTRANT
- static uint8_t data[1024 * 1024]; // keep this off of the stack
-#else
- uint8_t data[1024 * 1024];
-#endif
uint8_t buf[4 + 4 + 8 + 8 + 4];
uint32_t magic;
uint32_t type;
return -1;
}
- if (len > sizeof(data)) {
- LOG("len (%u) is larger than max len (%lu)",
- len, (unsigned long)sizeof(data));
+ if (len > data_size) {
+ LOG("len (%u) is larger than max len (%u)",
+ len, data_size);
errno = EINVAL;
return -1;
}
int nbd_negotiate(BlockDriverState *bs, int csock, off_t size);
int nbd_receive_negotiate(int csock, off_t *size, size_t *blocksize);
int nbd_init(int fd, int csock, off_t size, size_t blocksize);
-int nbd_trip(BlockDriverState *bs, int csock, off_t size, uint64_t dev_offset, off_t *offset, bool readonly);
+int nbd_trip(BlockDriverState *bs, int csock, off_t size, uint64_t dev_offset,
+ off_t *offset, bool readonly, uint8_t *data, int data_size);
int nbd_client(int fd, int csock);
int nbd_disconnect(int fd);
#define SOCKET_PATH "/var/lock/qemu-nbd-%s"
+#define NBD_BUFFER_SIZE (1024*1024)
+
int verbose;
static void usage(const char *name)
" (default '"SOCKET_PATH"')\n"
" -r, --read-only export read-only\n"
" -P, --partition=NUM only expose partition NUM\n"
+" -s, --snapshot use snapshot file\n"
+" -n, --nocache disable host cache\n"
" -c, --connect=DEV connect FILE to the local NBD device DEV\n"
" -d, --disconnect disconnect the specified device\n"
" -v, --verbose display extra debugging information\n"
char *device = NULL;
char *socket = NULL;
char sockpath[128];
- const char *sopt = "hVbo:p:rsP:c:dvk:";
+ const char *sopt = "hVbo:p:rsnP:c:dvk:";
struct option lopt[] = {
{ "help", 0, 0, 'h' },
{ "version", 0, 0, 'V' },
{ "connect", 1, 0, 'c' },
{ "disconnect", 0, 0, 'd' },
{ "snapshot", 0, 0, 's' },
+ { "nocache", 0, 0, 'n' },
{ "verbose", 0, 0, 'v' },
{ NULL, 0, 0, 0 }
};
int opt_ind = 0;
int li;
char *end;
- bool snapshot = false;
+ int flags = 0;
int partition = -1;
int fd;
int ret;
+ uint8_t *data;
while ((ch = getopt_long(argc, argv, sopt, lopt, &opt_ind)) != -1) {
switch (ch) {
case 's':
- snapshot = true;
+ flags |= BDRV_O_SNAPSHOT;
+ break;
+ case 'n':
+ flags |= BDRV_O_DIRECT;
break;
case 'b':
bindto = optarg;
if (bs == NULL)
return 1;
- if (bdrv_open(bs, argv[optind], snapshot) == -1)
+ if (bdrv_open(bs, argv[optind], flags) == -1)
return 1;
fd_size = bs->total_sectors * 512;
if (nbd_negotiate(bs, csock, fd_size) == -1)
return 1;
- while (nbd_trip(bs, csock, fd_size, dev_offset, &offset, readonly) == 0);
+ data = qemu_memalign(512, NBD_BUFFER_SIZE);
+ while (nbd_trip(bs, csock, fd_size, dev_offset, &offset, readonly,
+ data, NBD_BUFFER_SIZE) == 0);
+ qemu_free(data);
close(csock);
close(sock);
export read-only
@item -P, --partition=NUM
only expose partition NUM
+@item -s, --snapshot
+ use snapshot file
+@item -n, --nocache
+ disable host cache
@item -c, --connect
connect FILE to NBD device DEV
@item -d, --disconnect