mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	vhost/scsi: use vmalloc for order-10 allocation
As vhost scsi device struct is large, if the device is created on a busy system, kzalloc() might fail, so this patch does a fallback to vzalloc(). As vmalloc() adds overhead on data-path, add __GFP_REPEAT to kzalloc() flags to do this fallback only when really needed. Reviewed-by: Asias He <asias@redhat.com> Reported-by: Dan Aloni <alonid@stratoscale.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
This commit is contained in:
		
							parent
							
								
									ac9fde2474
								
							
						
					
					
						commit
						595cb75498
					
				
					 1 changed files with 27 additions and 14 deletions
				
			
		| 
						 | 
					@ -1373,21 +1373,30 @@ static int vhost_scsi_set_features(struct vhost_scsi *vs, u64 features)
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void vhost_scsi_free(struct vhost_scsi *vs)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (is_vmalloc_addr(vs))
 | 
				
			||||||
 | 
							vfree(vs);
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							kfree(vs);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int vhost_scsi_open(struct inode *inode, struct file *f)
 | 
					static int vhost_scsi_open(struct inode *inode, struct file *f)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct vhost_scsi *vs;
 | 
						struct vhost_scsi *vs;
 | 
				
			||||||
	struct vhost_virtqueue **vqs;
 | 
						struct vhost_virtqueue **vqs;
 | 
				
			||||||
	int r, i;
 | 
						int r = -ENOMEM, i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	vs = kzalloc(sizeof(*vs), GFP_KERNEL);
 | 
						vs = kzalloc(sizeof(*vs), GFP_KERNEL | __GFP_NOWARN | __GFP_REPEAT);
 | 
				
			||||||
 | 
						if (!vs) {
 | 
				
			||||||
 | 
							vs = vzalloc(sizeof(*vs));
 | 
				
			||||||
		if (!vs)
 | 
							if (!vs)
 | 
				
			||||||
		return -ENOMEM;
 | 
								goto err_vs;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	vqs = kmalloc(VHOST_SCSI_MAX_VQ * sizeof(*vqs), GFP_KERNEL);
 | 
						vqs = kmalloc(VHOST_SCSI_MAX_VQ * sizeof(*vqs), GFP_KERNEL);
 | 
				
			||||||
	if (!vqs) {
 | 
						if (!vqs)
 | 
				
			||||||
		kfree(vs);
 | 
							goto err_vqs;
 | 
				
			||||||
		return -ENOMEM;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	vhost_work_init(&vs->vs_completion_work, vhost_scsi_complete_cmd_work);
 | 
						vhost_work_init(&vs->vs_completion_work, vhost_scsi_complete_cmd_work);
 | 
				
			||||||
	vhost_work_init(&vs->vs_event_work, tcm_vhost_evt_work);
 | 
						vhost_work_init(&vs->vs_event_work, tcm_vhost_evt_work);
 | 
				
			||||||
| 
						 | 
					@ -1407,14 +1416,18 @@ static int vhost_scsi_open(struct inode *inode, struct file *f)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	tcm_vhost_init_inflight(vs, NULL);
 | 
						tcm_vhost_init_inflight(vs, NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (r < 0) {
 | 
						if (r < 0)
 | 
				
			||||||
		kfree(vqs);
 | 
							goto err_init;
 | 
				
			||||||
		kfree(vs);
 | 
					 | 
				
			||||||
		return r;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	f->private_data = vs;
 | 
						f->private_data = vs;
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					err_init:
 | 
				
			||||||
 | 
						kfree(vqs);
 | 
				
			||||||
 | 
					err_vqs:
 | 
				
			||||||
 | 
						vhost_scsi_free(vs);
 | 
				
			||||||
 | 
					err_vs:
 | 
				
			||||||
 | 
						return r;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int vhost_scsi_release(struct inode *inode, struct file *f)
 | 
					static int vhost_scsi_release(struct inode *inode, struct file *f)
 | 
				
			||||||
| 
						 | 
					@ -1431,7 +1444,7 @@ static int vhost_scsi_release(struct inode *inode, struct file *f)
 | 
				
			||||||
	/* Jobs can re-queue themselves in evt kick handler. Do extra flush. */
 | 
						/* Jobs can re-queue themselves in evt kick handler. Do extra flush. */
 | 
				
			||||||
	vhost_scsi_flush(vs);
 | 
						vhost_scsi_flush(vs);
 | 
				
			||||||
	kfree(vs->dev.vqs);
 | 
						kfree(vs->dev.vqs);
 | 
				
			||||||
	kfree(vs);
 | 
						vhost_scsi_free(vs);
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue