diff options
| -rw-r--r-- | drivers/vhost/scsi.c | 41 |
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 | ||
| 1376 | static 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 | |||
| 1376 | static int vhost_scsi_open(struct inode *inode, struct file *f) | 1384 | static 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 | |||
| 1425 | err_init: | ||
| 1426 | kfree(vqs); | ||
| 1427 | err_vqs: | ||
| 1428 | vhost_scsi_free(vs); | ||
| 1429 | err_vs: | ||
| 1430 | return r; | ||
| 1418 | } | 1431 | } |
| 1419 | 1432 | ||
| 1420 | static int vhost_scsi_release(struct inode *inode, struct file *f) | 1433 | 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) | |||
| 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 | ||
