Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

vdpa_sim_blk: support shared backend

The vdpa_sim_blk simulator uses a ramdisk as the backend. To test live
migration, we need two devices that share the backend to have the data
synchronized with each other.

Add a new module parameter to make the buffer shared between all devices.

The shared_buffer_mutex is used just to ensure that each operation is
atomic, but it is up to the user to use the devices knowing that the
underlying ramdisk is shared.

For example, when we do a migration, the VMM (e.g., QEMU) will guarantee
to write to the destination device, only after completing operations with
the source device.

Signed-off-by: Stefano Garzarella <sgarzare@redhat.com>
Message-Id: <20230407133658.66339-3-sgarzare@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>

authored by

Stefano Garzarella and committed by
Michael S. Tsirkin
abebb162 112f23cd

+49 -6
+49 -6
drivers/vdpa/vdpa_sim/vdpa_sim_blk.c
··· 46 46 struct vdpasim_blk { 47 47 struct vdpasim vdpasim; 48 48 void *buffer; 49 + bool shared_backend; 49 50 }; 50 51 51 52 static struct vdpasim_blk *sim_to_blk(struct vdpasim *vdpasim) ··· 55 54 } 56 55 57 56 static char vdpasim_blk_id[VIRTIO_BLK_ID_BYTES] = "vdpa_blk_sim"; 57 + 58 + static bool shared_backend; 59 + module_param(shared_backend, bool, 0444); 60 + MODULE_PARM_DESC(shared_backend, "Enable the shared backend between virtio-blk devices"); 61 + 62 + static void *shared_buffer; 63 + /* mutex to synchronize shared_buffer access */ 64 + static DEFINE_MUTEX(shared_buffer_mutex); 65 + 66 + static void vdpasim_blk_buffer_lock(struct vdpasim_blk *blk) 67 + { 68 + if (blk->shared_backend) 69 + mutex_lock(&shared_buffer_mutex); 70 + } 71 + 72 + static void vdpasim_blk_buffer_unlock(struct vdpasim_blk *blk) 73 + { 74 + if (blk->shared_backend) 75 + mutex_unlock(&shared_buffer_mutex); 76 + } 58 77 59 78 static bool vdpasim_blk_check_range(struct vdpasim *vdpasim, u64 start_sector, 60 79 u64 num_sectors, u64 max_sectors) ··· 175 154 break; 176 155 } 177 156 157 + vdpasim_blk_buffer_lock(blk); 178 158 bytes = vringh_iov_push_iotlb(&vq->vring, &vq->in_iov, 179 159 blk->buffer + offset, to_push); 160 + vdpasim_blk_buffer_unlock(blk); 180 161 if (bytes < 0) { 181 162 dev_dbg(&vdpasim->vdpa.dev, 182 163 "vringh_iov_push_iotlb() error: %zd offset: 0x%llx len: 0x%zx\n", ··· 198 175 break; 199 176 } 200 177 178 + vdpasim_blk_buffer_lock(blk); 201 179 bytes = vringh_iov_pull_iotlb(&vq->vring, &vq->out_iov, 202 180 blk->buffer + offset, to_pull); 181 + vdpasim_blk_buffer_unlock(blk); 203 182 if (bytes < 0) { 204 183 dev_dbg(&vdpasim->vdpa.dev, 205 184 "vringh_iov_pull_iotlb() error: %zd offset: 0x%llx len: 0x%zx\n", ··· 281 256 } 282 257 283 258 if (type == VIRTIO_BLK_T_WRITE_ZEROES) { 259 + vdpasim_blk_buffer_lock(blk); 284 260 memset(blk->buffer + offset, 0, 285 261 num_sectors << SECTOR_SHIFT); 262 + vdpasim_blk_buffer_unlock(blk); 286 263 } 287 264 288 265 break; ··· 393 366 { 394 367 struct vdpasim_blk *blk = sim_to_blk(vdpasim); 395 368 396 - kvfree(blk->buffer); 369 + if (!blk->shared_backend) 370 + kvfree(blk->buffer); 397 371 } 398 372 399 373 static void vdpasim_blk_mgmtdev_release(struct device *dev) ··· 432 404 return PTR_ERR(simdev); 433 405 434 406 blk = sim_to_blk(simdev); 407 + blk->shared_backend = shared_backend; 435 408 436 - blk->buffer = kvmalloc(VDPASIM_BLK_CAPACITY << SECTOR_SHIFT, 437 - GFP_KERNEL); 438 - if (!blk->buffer) { 439 - ret = -ENOMEM; 440 - goto put_dev; 409 + if (blk->shared_backend) { 410 + blk->buffer = shared_buffer; 411 + } else { 412 + blk->buffer = kvmalloc(VDPASIM_BLK_CAPACITY << SECTOR_SHIFT, 413 + GFP_KERNEL); 414 + if (!blk->buffer) { 415 + ret = -ENOMEM; 416 + goto put_dev; 417 + } 441 418 } 442 419 443 420 ret = _vdpa_register_device(&simdev->vdpa, VDPASIM_BLK_VQ_NUM); ··· 494 461 if (ret) 495 462 goto parent_err; 496 463 464 + if (shared_backend) { 465 + shared_buffer = kvmalloc(VDPASIM_BLK_CAPACITY << SECTOR_SHIFT, 466 + GFP_KERNEL); 467 + if (!shared_buffer) { 468 + ret = -ENOMEM; 469 + goto parent_err; 470 + } 471 + } 472 + 497 473 return 0; 498 474 499 475 parent_err: ··· 512 470 513 471 static void __exit vdpasim_blk_exit(void) 514 472 { 473 + kvfree(shared_buffer); 515 474 vdpa_mgmtdev_unregister(&mgmt_dev); 516 475 device_unregister(&vdpasim_blk_mgmtdev); 517 476 }