aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/vhost/scsi.c
diff options
context:
space:
mode:
authorMichael S. Tsirkin <mst@redhat.com>2013-09-17 02:30:34 -0400
committerMichael S. Tsirkin <mst@redhat.com>2013-09-17 15:55:46 -0400
commit595cb754983d4387cb25b3dcf08f5129663d634e (patch)
treefbd228ea66ec0cf53681efb952fc084a8b6603f0 /drivers/vhost/scsi.c
parentac9fde2474d04bd6574a037482e3de02b488a6c6 (diff)
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>
Diffstat (limited to 'drivers/vhost/scsi.c')
-rw-r--r--drivers/vhost/scsi.c41
1 files changed, 27 insertions, 14 deletions
diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c
index 4b79a1f2f901..38ccf4ad6b7a 100644
--- a/drivers/vhost/scsi.c
+++ b/drivers/vhost/scsi.c
@@ -1373,21 +1373,30 @@ static int vhost_scsi_set_features(struct vhost_scsi *vs, u64 features)
1373 return 0; 1373 return 0;
1374} 1374}
1375 1375
1376static void vhost_scsi_free(struct vhost_scsi *vs)
1377{
1378 if (is_vmalloc_addr(vs))
1379 vfree(vs);
1380 else
1381 kfree(vs);
1382}
1383
1376static int vhost_scsi_open(struct inode *inode, struct file *f) 1384static int vhost_scsi_open(struct inode *inode, struct file *f)
1377{ 1385{
1378 struct vhost_scsi *vs; 1386 struct vhost_scsi *vs;
1379 struct vhost_virtqueue **vqs; 1387 struct vhost_virtqueue **vqs;
1380 int r, i; 1388 int r = -ENOMEM, i;
1381 1389
1382 vs = kzalloc(sizeof(*vs), GFP_KERNEL); 1390 vs = kzalloc(sizeof(*vs), GFP_KERNEL | __GFP_NOWARN | __GFP_REPEAT);
1383 if (!vs) 1391 if (!vs) {
1384 return -ENOMEM; 1392 vs = vzalloc(sizeof(*vs));
1393 if (!vs)
1394 goto err_vs;
1395 }
1385 1396
1386 vqs = kmalloc(VHOST_SCSI_MAX_VQ * sizeof(*vqs), GFP_KERNEL); 1397 vqs = kmalloc(VHOST_SCSI_MAX_VQ * sizeof(*vqs), GFP_KERNEL);
1387 if (!vqs) { 1398 if (!vqs)
1388 kfree(vs); 1399 goto err_vqs;
1389 return -ENOMEM;
1390 }
1391 1400
1392 vhost_work_init(&vs->vs_completion_work, vhost_scsi_complete_cmd_work); 1401 vhost_work_init(&vs->vs_completion_work, vhost_scsi_complete_cmd_work);
1393 vhost_work_init(&vs->vs_event_work, tcm_vhost_evt_work); 1402 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)
1407 1416
1408 tcm_vhost_init_inflight(vs, NULL); 1417 tcm_vhost_init_inflight(vs, NULL);
1409 1418
1410 if (r < 0) { 1419 if (r < 0)
1411 kfree(vqs); 1420 goto err_init;
1412 kfree(vs);
1413 return r;
1414 }
1415 1421
1416 f->private_data = vs; 1422 f->private_data = vs;
1417 return 0; 1423 return 0;
1424
1425err_init:
1426 kfree(vqs);
1427err_vqs:
1428 vhost_scsi_free(vs);
1429err_vs:
1430 return r;
1418} 1431}
1419 1432
1420static int vhost_scsi_release(struct inode *inode, struct file *f) 1433static 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)
1431 /* Jobs can re-queue themselves in evt kick handler. Do extra flush. */ 1444 /* Jobs can re-queue themselves in evt kick handler. Do extra flush. */
1432 vhost_scsi_flush(vs); 1445 vhost_scsi_flush(vs);
1433 kfree(vs->dev.vqs); 1446 kfree(vs->dev.vqs);
1434 kfree(vs); 1447 vhost_scsi_free(vs);
1435 return 0; 1448 return 0;
1436} 1449}
1437 1450