Skip to content

Commit 54f9e32

Browse files
Yuanhan LiuThomas Monjalon
authored andcommitted
vhost: handle dirty pages logging request
VHOST_USER_SET_LOG_BASE request is used to tell the backend (dpdk vhost-user) where we should log dirty pages, and how big the log buffer is. This request introduces a new payload: typedef struct VhostUserLog { uint64_t mmap_size; uint64_t mmap_offset; } VhostUserLog; Also, a fd is delivered from QEMU by ancillary data. With those info given, an area of memory is mmaped, assigned to dev->log_base, for logging dirty pages. Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com> Signed-off-by: Victor Kaplansky <victork@redhat.com> Tested-by: Pavel Fedin <p.fedin@samsung.com>
1 parent f1fe838 commit 54f9e32

File tree

5 files changed

+63
-3
lines changed

5 files changed

+63
-3
lines changed

lib/librte_vhost/rte_virtio_net.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,9 @@ struct virtio_net {
129129
char ifname[IF_NAME_SZ]; /**< Name of the tap device or socket path. */
130130
uint32_t virt_qp_nb; /**< number of queue pair we have allocated */
131131
void *priv; /**< private context */
132-
uint64_t reserved[64]; /**< Reserve some spaces for future extension. */
132+
uint64_t log_size; /**< Size of log area */
133+
uint64_t log_base; /**< Where dirty pages are logged */
134+
uint64_t reserved[62]; /**< Reserve some spaces for future extension. */
133135
struct vhost_virtqueue *virtqueue[VHOST_MAX_QUEUE_PAIRS * 2]; /**< Contains all virtqueue information. */
134136
} __rte_cache_aligned;
135137

lib/librte_vhost/vhost_user/vhost-net-user.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -388,9 +388,12 @@ vserver_message_handler(int connfd, void *dat, int *remove)
388388
break;
389389

390390
case VHOST_USER_SET_LOG_BASE:
391-
RTE_LOG(INFO, VHOST_CONFIG, "not implemented.\n");
392-
break;
391+
user_set_log_base(ctx, &msg);
393392

393+
/* it needs a reply */
394+
msg.size = sizeof(msg.payload.u64);
395+
send_vhost_message(connfd, &msg);
396+
break;
394397
case VHOST_USER_SET_LOG_FD:
395398
close(msg.fds[0]);
396399
RTE_LOG(INFO, VHOST_CONFIG, "not implemented.\n");

lib/librte_vhost/vhost_user/vhost-net-user.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,11 @@ typedef struct VhostUserMemory {
8383
VhostUserMemoryRegion regions[VHOST_MEMORY_MAX_NREGIONS];
8484
} VhostUserMemory;
8585

86+
typedef struct VhostUserLog {
87+
uint64_t mmap_size;
88+
uint64_t mmap_offset;
89+
} VhostUserLog;
90+
8691
typedef struct VhostUserMsg {
8792
VhostUserRequest request;
8893

@@ -97,6 +102,7 @@ typedef struct VhostUserMsg {
97102
struct vhost_vring_state state;
98103
struct vhost_vring_addr addr;
99104
VhostUserMemory memory;
105+
VhostUserLog log;
100106
} payload;
101107
int fds[VHOST_MEMORY_MAX_NREGIONS];
102108
} __attribute((packed)) VhostUserMsg;

lib/librte_vhost/vhost_user/virtio-net-user.c

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -365,3 +365,51 @@ user_set_protocol_features(struct vhost_device_ctx ctx,
365365

366366
dev->protocol_features = protocol_features;
367367
}
368+
369+
int
370+
user_set_log_base(struct vhost_device_ctx ctx,
371+
struct VhostUserMsg *msg)
372+
{
373+
struct virtio_net *dev;
374+
int fd = msg->fds[0];
375+
uint64_t size, off;
376+
void *addr;
377+
378+
dev = get_device(ctx);
379+
if (!dev)
380+
return -1;
381+
382+
if (fd < 0) {
383+
RTE_LOG(ERR, VHOST_CONFIG, "invalid log fd: %d\n", fd);
384+
return -1;
385+
}
386+
387+
if (msg->size != sizeof(VhostUserLog)) {
388+
RTE_LOG(ERR, VHOST_CONFIG,
389+
"invalid log base msg size: %"PRId32" != %d\n",
390+
msg->size, (int)sizeof(VhostUserLog));
391+
return -1;
392+
}
393+
394+
size = msg->payload.log.mmap_size;
395+
off = msg->payload.log.mmap_offset;
396+
RTE_LOG(INFO, VHOST_CONFIG,
397+
"log mmap size: %"PRId64", offset: %"PRId64"\n",
398+
size, off);
399+
400+
/*
401+
* mmap from 0 to workaround a hugepage mmap bug: mmap will
402+
* fail when offset is not page size aligned.
403+
*/
404+
addr = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
405+
if (addr == MAP_FAILED) {
406+
RTE_LOG(ERR, VHOST_CONFIG, "mmap log base failed!\n");
407+
return -1;
408+
}
409+
410+
/* TODO: unmap on stop */
411+
dev->log_base = (uint64_t)(uintptr_t)addr + off;
412+
dev->log_size = size;
413+
414+
return 0;
415+
}

lib/librte_vhost/vhost_user/virtio-net-user.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ void user_set_vring_kick(struct vhost_device_ctx, struct VhostUserMsg *);
4949

5050
void user_set_protocol_features(struct vhost_device_ctx ctx,
5151
uint64_t protocol_features);
52+
int user_set_log_base(struct vhost_device_ctx ctx, struct VhostUserMsg *);
5253

5354
int user_get_vring_base(struct vhost_device_ctx, struct vhost_vring_state *);
5455

0 commit comments

Comments
 (0)