From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:34450) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1aJYXQ-0002If-Oa for qemu-devel@nongnu.org; Wed, 13 Jan 2016 22:25:29 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1aJYXN-0008UT-GT for qemu-devel@nongnu.org; Wed, 13 Jan 2016 22:25:28 -0500 Received: from mx1.redhat.com ([209.132.183.28]:46621) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1aJYXN-0008U0-8X for qemu-devel@nongnu.org; Wed, 13 Jan 2016 22:25:25 -0500 References: From: Jason Wang Message-ID: <5697151C.6090506@redhat.com> Date: Thu, 14 Jan 2016 11:25:16 +0800 MIME-Version: 1.0 In-Reply-To: Content-Type: text/plain; charset=windows-1252 Content-Transfer-Encoding: 7bit Subject: Re: [Qemu-devel] [PATCH 2/2] net: netmap: avoid mmap() when ports use the same shared memory area List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: Vincenzo Maffione , qemu-devel@nongnu.org Cc: g.lettieri@iet.unipi.it, rizzo@iet.unipi.it On 01/08/2016 09:15 PM, Vincenzo Maffione wrote: > With this patch, nm_open() does not mmap() the netmap device. This > operation is performed separately only if the memory area of the > port just opened was not known before. > A global list of netmap clients is kept to check when matches > occur. > > Signed-off-by: Vincenzo Maffione > --- > net/netmap.c | 38 +++++++++++++++++++++++++++++++++++++- > 1 file changed, 37 insertions(+), 1 deletion(-) > > diff --git a/net/netmap.c b/net/netmap.c > index 27295ab..6a4c01c 100644 > --- a/net/netmap.c > +++ b/net/netmap.c > @@ -49,8 +49,12 @@ typedef struct NetmapState { > bool write_poll; > struct iovec iov[IOV_MAX]; > int vnet_hdr_len; /* Current virtio-net header length. */ > + QTAILQ_ENTRY(NetmapState) next; > } NetmapState; > > +static QTAILQ_HEAD(, NetmapState) netmap_clients = > + QTAILQ_HEAD_INITIALIZER(netmap_clients); > + > #ifndef __FreeBSD__ > #define pkt_copy bcopy > #else > @@ -78,6 +82,23 @@ pkt_copy(const void *_src, void *_dst, int l) > #endif /* __FreeBSD__ */ > > /* > + * find nm_desc parent with same allocator > + */ > +static struct nm_desc * > +netmap_find_memory(struct nm_desc *nmd) > +{ > + NetmapState *s; > + > + QTAILQ_FOREACH(s, &netmap_clients, next) { > + if (nmd->req.nr_arg2 == s->nmd->req.nr_arg2) { > + return s->nmd; > + } > + } > + > + return NULL; > +} > + > +/* > * Open a netmap device. We assume there is only one queue > * (which is the case for the VALE bridge). > */ > @@ -86,10 +107,11 @@ static struct nm_desc *netmap_open(const NetdevNetmapOptions *nm_opts, > { > struct nm_desc *nmd; > struct nmreq req; > + int ret; > > memset(&req, 0, sizeof(req)); > > - nmd = nm_open(nm_opts->ifname, &req, NETMAP_NO_TX_POLL, > + nmd = nm_open(nm_opts->ifname, &req, NETMAP_NO_TX_POLL | NM_OPEN_NO_MMAP, > NULL); > if (nmd == NULL) { > error_setg_errno(errp, errno, "Failed to nm_open() %s", > @@ -97,6 +119,17 @@ static struct nm_desc *netmap_open(const NetdevNetmapOptions *nm_opts, > return NULL; > } > > + /* Check if we already have a nm_desc that uses the same memory as the one > + * just opened, so that nm_mmap() can skip mmap() and inherit from parent. > + */ > + ret = nm_mmap(nmd, netmap_find_memory(nmd)); Looks like I could not find nm_mmap() definition in neither qemu or freebsd source. Is there anything missed? > + if (ret) { > + error_setg_errno(errp, errno, "Failed to nm_mmap() %s", > + nm_opts->ifname); > + nm_close(nmd); > + return NULL; > + } > + > return nmd; > } > > @@ -321,6 +354,8 @@ static void netmap_cleanup(NetClientState *nc) > netmap_poll(nc, false); > nm_close(s->nmd); > s->nmd = NULL; > + > + QTAILQ_REMOVE(&netmap_clients, s, next); > } > > /* Offloading manipulation support callbacks. */ > @@ -423,6 +458,7 @@ int net_init_netmap(const NetClientOptions *opts, > s->rx = NETMAP_RXRING(nmd->nifp, 0); > s->vnet_hdr_len = 0; > pstrcpy(s->ifname, sizeof(s->ifname), netmap_opts->ifname); > + QTAILQ_INSERT_TAIL(&netmap_clients, s, next); > netmap_read_poll(s, true); /* Initially only poll for reads. */ > > return 0;