From: "Dr. David Alan Gilbert" <dgilb...@redhat.com> The 'meta data version table' is a block of shared memory mapped between multiple QEMUs and fuse daemons, so that they can be informed of metadata updates. It's typically a shmfs file, and it's specified as :
-device vhost-user-fs-pci,chardev=char0,tag=myfs,cache-size=1G,versiontable=/dev/shm/mdvt1 It gets mapped into the PCI bar after the data cache; it's read only. Signed-off-by: Dr. David Alan Gilbert <dgilb...@redhat.com> --- hw/virtio/vhost-user-fs.c | 36 ++++++++++++++++++++++ hw/virtio/virtio-pci.c | 16 ++++++++-- include/hw/virtio/vhost-user-fs.h | 4 +++ include/standard-headers/linux/virtio_fs.h | 1 + 4 files changed, 55 insertions(+), 2 deletions(-) diff --git a/hw/virtio/vhost-user-fs.c b/hw/virtio/vhost-user-fs.c index bbb15477e5..a39ecd3a16 100644 --- a/hw/virtio/vhost-user-fs.c +++ b/hw/virtio/vhost-user-fs.c @@ -296,6 +296,7 @@ static void vuf_device_realize(DeviceState *dev, Error **errp) unsigned int i; size_t len; int ret; + int mdvtfd = -1; if (!fs->conf.chardev.chr) { error_setg(errp, "missing chardev"); @@ -338,6 +339,31 @@ static void vuf_device_realize(DeviceState *dev, Error **errp) "no smaller than the page size"); return; } + + if (fs->conf.mdvtpath) { + struct stat statbuf; + + mdvtfd = open(fs->conf.mdvtpath, O_RDWR); + if (mdvtfd < 0) { + error_setg_errno(errp, errno, + "Failed to open meta-data version table '%s'", + fs->conf.mdvtpath); + + return; + } + if (fstat(mdvtfd, &statbuf) == -1) { + error_setg_errno(errp, errno, + "Failed to stat meta-data version table '%s'", + fs->conf.mdvtpath); + close(mdvtfd); + return; + } + + fs->mdvt_size = statbuf.st_size; + } + fprintf(stderr, "%s: cachesize=%zd mdvt_size=%zd\n", __func__, + fs->conf.cache_size, fs->mdvt_size); + /* We need a region with some host memory, 'ram' is the easiest */ memory_region_init_ram_nomigrate(&fs->cache, OBJECT(vdev), "virtio-fs-cache", @@ -348,6 +374,15 @@ static void vuf_device_realize(DeviceState *dev, Error **errp) mprotect(memory_region_get_ram_ptr(&fs->cache), fs->conf.cache_size, PROT_NONE); + + if (mdvtfd) { + memory_region_init_ram_from_fd(&fs->mdvt, OBJECT(vdev), + "virtio-fs-mdvt", + fs->mdvt_size, true, mdvtfd, NULL); + /* The version table is read-only by the guest */ + memory_region_set_readonly(&fs->mdvt, true); + } + fs->vhost_user = vhost_user_init(); if (!fs->vhost_user) { error_setg(errp, "failed to initialize vhost-user"); @@ -416,6 +451,7 @@ static Property vuf_properties[] = { DEFINE_PROP_UINT16("queue-size", VHostUserFS, conf.queue_size, 128), DEFINE_PROP_STRING("vhostfd", VHostUserFS, conf.vhostfd), DEFINE_PROP_SIZE("cache-size", VHostUserFS, conf.cache_size, 1ull << 30), + DEFINE_PROP_STRING("versiontable", VHostUserFS, conf.mdvtpath), DEFINE_PROP_END_OF_LIST(), }; diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c index e819a29fb1..d8785b78bf 100644 --- a/hw/virtio/virtio-pci.c +++ b/hw/virtio/virtio-pci.c @@ -2680,20 +2680,32 @@ static void vhost_user_fs_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp) VHostUserFSPCI *dev = VHOST_USER_FS_PCI(vpci_dev); DeviceState *vdev = DEVICE(&dev->vdev); uint64_t cachesize; + uint64_t totalsize; qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus)); object_property_set_bool(OBJECT(vdev), true, "realized", errp); cachesize = memory_region_size(&dev->vdev.cache); + /* PCIe bar needs to be a power of 2 */ + totalsize = pow2ceil(cachesize + dev->vdev.mdvt_size); + /* The bar starts with the data/DAX cache - * Others will be added later. + * followed by the metadata cache. */ memory_region_init(&dev->cachebar, OBJECT(vpci_dev), - "vhost-fs-pci-cachebar", cachesize); + "vhost-fs-pci-cachebar", totalsize); memory_region_add_subregion(&dev->cachebar, 0, &dev->vdev.cache); virtio_pci_add_shm_cap(vpci_dev, VIRTIO_FS_PCI_CACHE_BAR, 0, cachesize, VIRTIO_FS_PCI_SHMCAP_ID_CACHE); + if (dev->vdev.mdvt_size) { + memory_region_add_subregion(&dev->cachebar, cachesize, + &dev->vdev.mdvt); + virtio_pci_add_shm_cap(vpci_dev, VIRTIO_FS_PCI_CACHE_BAR, + cachesize, dev->vdev.mdvt_size, + VIRTIO_FS_PCI_SHMCAP_ID_VERTAB); + } + /* After 'realized' so the memory region exists */ pci_register_bar(&vpci_dev->pci_dev, VIRTIO_FS_PCI_CACHE_BAR, PCI_BASE_ADDRESS_SPACE_MEMORY | diff --git a/include/hw/virtio/vhost-user-fs.h b/include/hw/virtio/vhost-user-fs.h index 9989bcd9e7..281ae0a52d 100644 --- a/include/hw/virtio/vhost-user-fs.h +++ b/include/hw/virtio/vhost-user-fs.h @@ -48,6 +48,7 @@ typedef struct { uint16_t queue_size; char *vhostfd; size_t cache_size; + char *mdvtpath; } VHostUserFSConf; typedef struct { @@ -60,6 +61,9 @@ typedef struct { /*< public >*/ MemoryRegion cache; + /* Metadata version table */ + size_t mdvt_size; + MemoryRegion mdvt; } VHostUserFS; /* Callbacks from the vhost-user code for slave commands */ diff --git a/include/standard-headers/linux/virtio_fs.h b/include/standard-headers/linux/virtio_fs.h index b5f137ca79..77fa651073 100644 --- a/include/standard-headers/linux/virtio_fs.h +++ b/include/standard-headers/linux/virtio_fs.h @@ -42,5 +42,6 @@ struct virtio_fs_config { /* For the id field in virtio_pci_shm_cap */ #define VIRTIO_FS_PCI_SHMCAP_ID_CACHE 0 +#define VIRTIO_FS_PCI_SHMCAP_ID_VERTAB 1 #endif /* _LINUX_VIRTIO_FS_H */ -- 2.19.2