bus/vmbus: map to the correct ring buffer addresses for the secondary process
PATCH 1/1 bus/vmbus: map to the correct ring buffer addresses for the secondary process
From: Long Li <[email protected]>
The driver code had wrong assumption that all the addresses to ring buffers in the secondary process are the same as those in the primary process. This is not always correct as the channels could be mapped to different addresses in the secondary process.
Fix this by keeping track of all the mapped addresses from the primary process in the shared uio_res, and have second process map to the same addresses.
--- drivers/bus/vmbus/linux/vmbus_uio.c | 97 +++++++++++++++------------- drivers/bus/vmbus/private.h | 15 ++++- drivers/bus/vmbus/vmbus_channel.c | 4 +- drivers/bus/vmbus/vmbus_common_uio.c | 52 +++++++++++---- 4 files changed, 105 insertions(+), 63 deletions(-)
drivers/bus/vmbus/linux/vmbus_uio.c +51 -46
@@ -203,6 +203,36 @@ static int vmbus_uio_map_subchan(const struct rte_vmbus_device *dev,struct stat sb;void *mapaddr;int fd; +struct mapped_vmbus_resource *uio_res; +int channel_idx; + + uio_res =vmbus_uio_find_resource (dev); +if (!uio_res) { +VMBUS_LOG (ERR ,"can not find resources for mapping subchan" ); +return -ENOMEM ; + } + +if (rte_eal_process_type () ==RTE_PROC_PRIMARY ) { +if (uio_res->nb_subchannels >=UIO_MAX_SUBCHANNEL ) { +VMBUS_LOG (ERR ,"exceeding max subchannels" +" UIO_MAX_SUBCHANNEL(%d). Increase this value" +" and recompile" , +UIO_MAX_SUBCHANNEL ); +return -ENOMEM ; + } + }else { +for (channel_idx =0 ; channel_idx < uio_res->nb_subchannels; + channel_idx++) +if (uio_res->subchannel_maps[channel_idx].relid == + chan->relid) +break ; +if (channel_idx == uio_res->nb_subchannels) { +VMBUS_LOG (ERR ,"couldn't find sub channel %d from" +" shared mapping in primary" , chan->relid); +return -ENOMEM ; + } + vmbus_map_addr = uio_res->subchannel_maps[channel_idx].addr; + } snprintf(ring_path, sizeof(ring_path), "%s/%s/channels/%u/ring",
@@ -239,58 +269,33 @@ static int vmbus_uio_map_subchan(const struct rte_vmbus_device *dev,if (mapaddr ==MAP_FAILED )return -EIO ; +if (rte_eal_process_type () ==RTE_PROC_PRIMARY ) { + +/* Add this mapping to uio_res for use by secondary */ + uio_res->subchannel_maps[uio_res->nb_subchannels].relid = + chan->relid; + uio_res->subchannel_maps[uio_res->nb_subchannels].addr = + mapaddr; + uio_res->subchannel_maps[uio_res->nb_subchannels].size = + file_size; + uio_res->nb_subchannels++; + + vmbus_map_addr =RTE_PTR_ADD (mapaddr, file_size); + }else { +if (mapaddr != vmbus_map_addr) { +VMBUS_LOG (ERR ,"failed to map channel %d to addr %p" , + chan->relid, mapaddr); +vmbus_unmap_resource (mapaddr, file_size); +return -EIO ; + } + } + *ring_size = file_size /2 ; *ring_buf = mapaddr; - vmbus_map_addr =RTE_PTR_ADD (mapaddr, file_size);return 0 ; } -int -vmbus_uio_map_secondary_subchan (const struct rte_vmbus_device *dev, -const struct vmbus_channel *chan) -{ -const struct vmbus_br *br = &chan->txbr; -char ring_path[PATH_MAX ]; -void *mapaddr, *ring_buf; -uint32_t ring_size; -int fd; - -snprintf (ring_path,sizeof (ring_path), -"%s/%s/channels/%u/ring" , -SYSFS_VMBUS_DEVICES , dev->device.name, - chan->relid); - - ring_buf = br->vbr; - ring_size = br->dsize +sizeof (struct vmbus_bufring ); -VMBUS_LOG (INFO ,"secondary ring_buf %p size %u" , - ring_buf, ring_size); - - fd =open (ring_path,O_RDWR ); -if (fd <0 ) { -VMBUS_LOG (ERR ,"Cannot open %s: %s" , - ring_path,strerror (errno)); -return -errno; - } - - mapaddr =vmbus_map_resource (ring_buf, fd,0 ,2 * ring_size,0 ); -close (fd); - -if (mapaddr == ring_buf) -return 0 ; - -if (mapaddr ==MAP_FAILED ) -VMBUS_LOG (ERR , -"mmap subchan %u in secondary failed" , chan->relid); -else { -VMBUS_LOG (ERR , -"mmap subchan %u in secondary address mismatch" , - chan->relid); -vmbus_unmap_resource (mapaddr,2 * ring_size); - } -return -1 ; -} -int vmbus_uio_map_rings (struct vmbus_channel *chan) {const struct rte_vmbus_device *dev = chan->device;
drivers/bus/vmbus/private.h +12 -3
@@ -33,6 +33,13 @@ struct vmbus_map {uint64_t size;/* length */ }; +#define UIO_MAX_SUBCHANNEL 128 +struct subchannel_map { +uint16_t relid; +void *addr; +uint64_t size; +}; +/* * For multi-process we need to reproduce all vmbus mappings in secondary * processes, so save them in a tailq.
@@ -41,10 +48,14 @@ struct mapped_vmbus_resource {TAILQ_ENTRY (mapped_vmbus_resource) next;rte_uuid_t id; +int nb_maps; -struct vmbus_channel *primary;struct vmbus_map maps[VMBUS_MAX_RESOURCE ]; +char path[PATH_MAX ]; + +int nb_subchannels; +struct subchannel_map subchannel_maps[UIO_MAX_SUBCHANNEL ]; };TAILQ_HEAD (mapped_vmbus_res_list, mapped_vmbus_resource);
@@ -105,8 +116,6 @@ bool vmbus_uio_subchannels_supported(const struct rte_vmbus_device *dev,int vmbus_uio_get_subchan (struct vmbus_channel *primary,struct vmbus_channel **subchan);int vmbus_uio_map_rings (struct vmbus_channel *chan); -int vmbus_uio_map_secondary_subchan (const struct rte_vmbus_device *dev, -const struct vmbus_channel *chan);void vmbus_br_setup (struct vmbus_br *br,void *buf,unsigned int blen);
drivers/bus/vmbus/vmbus_channel.c +1 -3
@@ -351,10 +351,8 @@ int rte_vmbus_chan_open(struct rte_vmbus_device *device, err =vmbus_chan_create (device, device->relid,0 , device->monitor_id, new_chan); -if (!err) { +if (!err) device->primary = *new_chan; - uio_res->primary = *new_chan; - }return err; }
drivers/bus/vmbus/vmbus_common_uio.c +41 -11
82 lines not on this page · raw message
Signature · 1 line
2.25.1
Quoted 7 lines · On Mon, 30 Aug 2021 22:56:44 -0700 [email protected] wrote:
From: Long Li <[email protected]>
The driver code had wrong assumption that all the addresses to ring buffers in the secondary process are the same as those in the primary process. This is not always correct as the channels could be mapped to different addresses in the secondary process.
Quoted 7 lines
Fix this by keeping track of all the mapped addresses from the primary process in the shared
uio_res, and have second process map to the same addresses.Reported-by Jonathan Erb <[email protected]>Signed-off-by Long Li <[email protected]>
I prefer that messages not get split across lines, but this looks fine.