diff mbox series

[2/3] virtio: cache indirect desc for packed

Message ID 20211027061913.76276-3-xuanzhuo@linux.alibaba.com (mailing list archive)
State Superseded
Headers show
Series virtio support cache indirect desc | expand

Checks

Context Check Description
netdev/tree_selection success Not a local patch

Commit Message

Xuan Zhuo Oct. 27, 2021, 6:19 a.m. UTC
In the case of using indirect, indirect desc must be allocated and
released each time, which increases a lot of cpu overhead.

Here, a cache is added for indirect. If the number of indirect desc to be
applied for is less than VIRT_QUEUE_CACHE_DESC_NUM, the desc array with
the size of VIRT_QUEUE_CACHE_DESC_NUM is fixed and cached for reuse.

Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
---
 drivers/virtio/virtio_ring.c | 57 +++++++++++++++++++++++++++++++-----
 1 file changed, 49 insertions(+), 8 deletions(-)

Comments

kernel test robot Oct. 28, 2021, 12:28 a.m. UTC | #1
Hi Xuan,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on horms-ipvs/master]
[also build test WARNING on linus/master v5.15-rc7]
[cannot apply to mst-vhost/linux-next next-20211027]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Xuan-Zhuo/virtio-support-cache-indirect-desc/20211027-142025
base:   https://git.kernel.org/pub/scm/linux/kernel/git/horms/ipvs.git master
config: hexagon-randconfig-r045-20211027 (attached as .config)
compiler: clang version 14.0.0 (https://github.com/llvm/llvm-project 5db7568a6a1fcb408eb8988abdaff2a225a8eb72)
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/0day-ci/linux/commit/bb65ceda850ed4592d8a940e01926d5e3d33ae92
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Xuan-Zhuo/virtio-support-cache-indirect-desc/20211027-142025
        git checkout bb65ceda850ed4592d8a940e01926d5e3d33ae92
        # save the attached .config to linux build tree
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 ARCH=hexagon 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All warnings (new ones prefixed by >>):

>> drivers/virtio/virtio_ring.c:1467:7: warning: variable 'len' is uninitialized when used here [-Wuninitialized]
                   n = len / sizeof(struct vring_packed_desc);
                       ^~~
   drivers/virtio/virtio_ring.c:1460:10: note: initialize the variable 'len' to silence this warning
                   u32 len, n;
                          ^
                           = 0
   1 warning generated.


vim +/len +1467 drivers/virtio/virtio_ring.c

  1433	
  1434	static void detach_buf_packed(struct vring_virtqueue *vq,
  1435				      unsigned int id, void **ctx)
  1436	{
  1437		struct vring_desc_state_packed *state = NULL;
  1438		struct vring_packed_desc *desc;
  1439		unsigned int i, curr;
  1440	
  1441		state = &vq->packed.desc_state[id];
  1442	
  1443		/* Clear data ptr. */
  1444		state->data = NULL;
  1445	
  1446		vq->packed.desc_extra[state->last].next = vq->free_head;
  1447		vq->free_head = id;
  1448		vq->vq.num_free += state->num;
  1449	
  1450		if (unlikely(vq->use_dma_api)) {
  1451			curr = id;
  1452			for (i = 0; i < state->num; i++) {
  1453				vring_unmap_state_packed(vq,
  1454					&vq->packed.desc_extra[curr]);
  1455				curr = vq->packed.desc_extra[curr].next;
  1456			}
  1457		}
  1458	
  1459		if (vq->indirect) {
  1460			u32 len, n;
  1461	
  1462			/* Free the indirect table, if any, now that it's unmapped. */
  1463			desc = state->indir_desc;
  1464			if (!desc)
  1465				return;
  1466	
> 1467			n = len / sizeof(struct vring_packed_desc);
  1468	
  1469			if (vq->use_dma_api) {
  1470				len = vq->packed.desc_extra[id].len;
  1471				for (i = 0; i < n; i++)
  1472					vring_unmap_desc_packed(vq, &desc[i]);
  1473			}
  1474	
  1475			desc_cache_put_packed(vq, desc, n);
  1476			state->indir_desc = NULL;
  1477		} else if (ctx) {
  1478			*ctx = state->indir_desc;
  1479		}
  1480	}
  1481	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
kernel test robot Oct. 28, 2021, 3:51 a.m. UTC | #2
Hi Xuan,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on horms-ipvs/master]
[also build test WARNING on linus/master v5.15-rc7]
[cannot apply to mst-vhost/linux-next next-20211027]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Xuan-Zhuo/virtio-support-cache-indirect-desc/20211027-142025
base:   https://git.kernel.org/pub/scm/linux/kernel/git/horms/ipvs.git master
config: i386-randconfig-s002-20211027 (attached as .config)
compiler: gcc-9 (Debian 9.3.0-22) 9.3.0
reproduce:
        # apt-get install sparse
        # sparse version: v0.6.4-dirty
        # https://github.com/0day-ci/linux/commit/bb65ceda850ed4592d8a940e01926d5e3d33ae92
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Xuan-Zhuo/virtio-support-cache-indirect-desc/20211027-142025
        git checkout bb65ceda850ed4592d8a940e01926d5e3d33ae92
        # save the attached .config to linux build tree
        make W=1 C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__' O=build_dir ARCH=i386 SHELL=/bin/bash drivers/virtio/

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>


sparse warnings: (new ones prefixed by >>)
   drivers/virtio/virtio_ring.c:438:26: sparse: sparse: cast from restricted __virtio64
   drivers/virtio/virtio_ring.c:447:28: sparse: sparse: incorrect type in assignment (different base types) @@     expected restricted __virtio64 [usertype] addr @@     got unsigned long long [usertype] @@
   drivers/virtio/virtio_ring.c:447:28: sparse:     expected restricted __virtio64 [usertype] addr
   drivers/virtio/virtio_ring.c:447:28: sparse:     got unsigned long long [usertype]
   drivers/virtio/virtio_ring.c:464:49: sparse: sparse: cast from restricted __virtio64
>> drivers/virtio/virtio_ring.c:1083:26: sparse: sparse: cast from restricted __le64
>> drivers/virtio/virtio_ring.c:1092:28: sparse: sparse: incorrect type in assignment (different base types) @@     expected restricted __le64 [usertype] addr @@     got unsigned long long [usertype] @@
   drivers/virtio/virtio_ring.c:1092:28: sparse:     expected restricted __le64 [usertype] addr
   drivers/virtio/virtio_ring.c:1092:28: sparse:     got unsigned long long [usertype]
   drivers/virtio/virtio_ring.c:1109:49: sparse: sparse: cast from restricted __le64

vim +1083 drivers/virtio/virtio_ring.c

  1076	
  1077	static void desc_cache_chain_free_packed(void *chain)
  1078	{
  1079		struct vring_packed_desc *desc;
  1080	
  1081		while (chain) {
  1082			desc = chain;
> 1083			chain = (void *)desc->addr;
  1084			kfree(desc);
  1085		}
  1086	}
  1087	
  1088	static void desc_cache_put_packed(struct vring_virtqueue *vq,
  1089					  struct vring_packed_desc *desc, int n)
  1090	{
  1091		if (vq->use_desc_cache && n <= VIRT_QUEUE_CACHE_DESC_NUM) {
> 1092			desc->addr = (u64)vq->desc_cache_chain;
  1093			vq->desc_cache_chain = desc;
  1094		} else {
  1095			kfree(desc);
  1096		}
  1097	}
  1098	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
kernel test robot Oct. 28, 2021, 7:38 a.m. UTC | #3
Hi Xuan,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on horms-ipvs/master]
[also build test ERROR on linus/master v5.15-rc7]
[cannot apply to mst-vhost/linux-next next-20211027]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Xuan-Zhuo/virtio-support-cache-indirect-desc/20211027-142025
base:   https://git.kernel.org/pub/scm/linux/kernel/git/horms/ipvs.git master
config: i386-buildonly-randconfig-r005-20211027 (attached as .config)
compiler: clang version 14.0.0 (https://github.com/llvm/llvm-project 5db7568a6a1fcb408eb8988abdaff2a225a8eb72)
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/0day-ci/linux/commit/bb65ceda850ed4592d8a940e01926d5e3d33ae92
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Xuan-Zhuo/virtio-support-cache-indirect-desc/20211027-142025
        git checkout bb65ceda850ed4592d8a940e01926d5e3d33ae92
        # save the attached .config to linux build tree
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 ARCH=i386 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All errors (new ones prefixed by >>):

>> drivers/virtio/virtio_ring.c:1467:7: error: variable 'len' is uninitialized when used here [-Werror,-Wuninitialized]
                   n = len / sizeof(struct vring_packed_desc);
                       ^~~
   drivers/virtio/virtio_ring.c:1460:10: note: initialize the variable 'len' to silence this warning
                   u32 len, n;
                          ^
                           = 0
   1 error generated.


vim +/len +1467 drivers/virtio/virtio_ring.c

  1433	
  1434	static void detach_buf_packed(struct vring_virtqueue *vq,
  1435				      unsigned int id, void **ctx)
  1436	{
  1437		struct vring_desc_state_packed *state = NULL;
  1438		struct vring_packed_desc *desc;
  1439		unsigned int i, curr;
  1440	
  1441		state = &vq->packed.desc_state[id];
  1442	
  1443		/* Clear data ptr. */
  1444		state->data = NULL;
  1445	
  1446		vq->packed.desc_extra[state->last].next = vq->free_head;
  1447		vq->free_head = id;
  1448		vq->vq.num_free += state->num;
  1449	
  1450		if (unlikely(vq->use_dma_api)) {
  1451			curr = id;
  1452			for (i = 0; i < state->num; i++) {
  1453				vring_unmap_state_packed(vq,
  1454					&vq->packed.desc_extra[curr]);
  1455				curr = vq->packed.desc_extra[curr].next;
  1456			}
  1457		}
  1458	
  1459		if (vq->indirect) {
  1460			u32 len, n;
  1461	
  1462			/* Free the indirect table, if any, now that it's unmapped. */
  1463			desc = state->indir_desc;
  1464			if (!desc)
  1465				return;
  1466	
> 1467			n = len / sizeof(struct vring_packed_desc);
  1468	
  1469			if (vq->use_dma_api) {
  1470				len = vq->packed.desc_extra[id].len;
  1471				for (i = 0; i < n; i++)
  1472					vring_unmap_desc_packed(vq, &desc[i]);
  1473			}
  1474	
  1475			desc_cache_put_packed(vq, desc, n);
  1476			state->indir_desc = NULL;
  1477		} else if (ctx) {
  1478			*ctx = state->indir_desc;
  1479		}
  1480	}
  1481	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
diff mbox series

Patch

diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
index 0b9a8544b0e8..4fd7bd5bcd70 100644
--- a/drivers/virtio/virtio_ring.c
+++ b/drivers/virtio/virtio_ring.c
@@ -1074,10 +1074,45 @@  static void vring_unmap_desc_packed(const struct vring_virtqueue *vq,
 	}
 }
 
-static struct vring_packed_desc *alloc_indirect_packed(unsigned int total_sg,
+static void desc_cache_chain_free_packed(void *chain)
+{
+	struct vring_packed_desc *desc;
+
+	while (chain) {
+		desc = chain;
+		chain = (void *)desc->addr;
+		kfree(desc);
+	}
+}
+
+static void desc_cache_put_packed(struct vring_virtqueue *vq,
+				  struct vring_packed_desc *desc, int n)
+{
+	if (vq->use_desc_cache && n <= VIRT_QUEUE_CACHE_DESC_NUM) {
+		desc->addr = (u64)vq->desc_cache_chain;
+		vq->desc_cache_chain = desc;
+	} else {
+		kfree(desc);
+	}
+}
+
+static struct vring_packed_desc *alloc_indirect_packed(struct vring_virtqueue *vq,
+						       unsigned int total_sg,
 						       gfp_t gfp)
 {
 	struct vring_packed_desc *desc;
+	unsigned int n;
+
+	if (vq->use_desc_cache && total_sg <= VIRT_QUEUE_CACHE_DESC_NUM) {
+		if (vq->desc_cache_chain) {
+			desc = vq->desc_cache_chain;
+			vq->desc_cache_chain = (void *)desc->addr;
+			return desc;
+		}
+		n = VIRT_QUEUE_CACHE_DESC_NUM;
+	} else {
+		n = total_sg;
+	}
 
 	/*
 	 * We require lowmem mappings for the descriptors because
@@ -1086,7 +1121,7 @@  static struct vring_packed_desc *alloc_indirect_packed(unsigned int total_sg,
 	 */
 	gfp &= ~__GFP_HIGHMEM;
 
-	desc = kmalloc_array(total_sg, sizeof(struct vring_packed_desc), gfp);
+	desc = kmalloc_array(n, sizeof(struct vring_packed_desc), gfp);
 
 	return desc;
 }
@@ -1106,7 +1141,7 @@  static int virtqueue_add_indirect_packed(struct vring_virtqueue *vq,
 	dma_addr_t addr;
 
 	head = vq->packed.next_avail_idx;
-	desc = alloc_indirect_packed(total_sg, gfp);
+	desc = alloc_indirect_packed(vq, total_sg, gfp);
 
 	if (unlikely(vq->vq.num_free < 1)) {
 		pr_debug("Can't add buf len 1 - avail = 0\n");
@@ -1197,7 +1232,7 @@  static int virtqueue_add_indirect_packed(struct vring_virtqueue *vq,
 	for (i = 0; i < err_idx; i++)
 		vring_unmap_desc_packed(vq, &desc[i]);
 
-	kfree(desc);
+	desc_cache_put_packed(vq, desc, total_sg);
 
 	END_USE(vq);
 	return -ENOMEM;
@@ -1422,20 +1457,22 @@  static void detach_buf_packed(struct vring_virtqueue *vq,
 	}
 
 	if (vq->indirect) {
-		u32 len;
+		u32 len, n;
 
 		/* Free the indirect table, if any, now that it's unmapped. */
 		desc = state->indir_desc;
 		if (!desc)
 			return;
 
+		n = len / sizeof(struct vring_packed_desc);
+
 		if (vq->use_dma_api) {
 			len = vq->packed.desc_extra[id].len;
-			for (i = 0; i < len / sizeof(struct vring_packed_desc);
-					i++)
+			for (i = 0; i < n; i++)
 				vring_unmap_desc_packed(vq, &desc[i]);
 		}
-		kfree(desc);
+
+		desc_cache_put_packed(vq, desc, n);
 		state->indir_desc = NULL;
 	} else if (ctx) {
 		*ctx = state->indir_desc;
@@ -1753,6 +1790,8 @@  static struct virtqueue *vring_create_virtqueue_packed(
 	vq->indirect = virtio_has_feature(vdev, VIRTIO_RING_F_INDIRECT_DESC) &&
 		!context;
 	vq->event = virtio_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX);
+	vq->desc_cache_chain = NULL;
+	vq->use_desc_cache = vdev->desc_cache;
 
 	if (virtio_has_feature(vdev, VIRTIO_F_ORDER_PLATFORM))
 		vq->weak_barriers = false;
@@ -2374,6 +2413,8 @@  void vring_del_virtqueue(struct virtqueue *_vq)
 		kfree(vq->split.desc_state);
 		kfree(vq->split.desc_extra);
 		desc_cache_chain_free_split(vq->desc_cache_chain);
+	} else {
+		desc_cache_chain_free_packed(vq->desc_cache_chain);
 	}
 	kfree(vq);
 }