virtio, vhost: fixes, tweaks
No new features but a bunch of tweaks such as switching balloon from oom notifier to shrinker. Signed-off-by: Michael S. Tsirkin <mst@redhat.com> -----BEGIN PGP SIGNATURE----- iQEcBAABAgAGBQJbfIxQAAoJECgfDbjSjVRp/3AH/1z+pJMvkDQN412qVOFEo+BI gRnTBw+0XdnR76eug11PFhMqBupQXwJ26NHfmSkoxqXy2NwRxX5Za2dHE1KJ+Sws NeBfwVIqwFBufGHMG7Uq/JNsLgSEB/ketNPWnJIzNVQbQOfdGbhmYMyS0nSy4S8m JcZX/iwA7XTxApSL5IWCM0ScddgFTdTkB6K/me8XNnIFWsX0mnRWly+L/7CDNx18 QdKWsAimZxIjtF6DIYieph1oirzeWmAf42raEghNe1dSeT3k4CnU+hYw/ofMo9Wm 5gtFRLP8vTyR1zlaSTDxElgFcTwwgiTpkX+xd1htegrm8M7Yd3RO/WUTFCFPhf4= =JrpR -----END PGP SIGNATURE----- Merge tag 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost Pull virtio updates from Michael Tsirkin: "virtio, vhost: fixes, tweaks No new features but a bunch of tweaks such as switching balloon from oom notifier to shrinker" * tag 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost: vhost/scsi: increase VHOST_SCSI_PREALLOC_PROT_SGLS to 2048 vhost: allow vhost-scsi driver to be built-in virtio: pci-legacy: Validate queue pfn virtio: mmio-v1: Validate queue PFN virtio_balloon: replace oom notifier with shrinker virtio-balloon: kzalloc the vb struct virtio-balloon: remove BUG() in init_vqs
This commit is contained in:
commit
d002924f93
|
@ -12,7 +12,7 @@ config VHOST_NET
|
||||||
|
|
||||||
config VHOST_SCSI
|
config VHOST_SCSI
|
||||||
tristate "VHOST_SCSI TCM fabric driver"
|
tristate "VHOST_SCSI TCM fabric driver"
|
||||||
depends on TARGET_CORE && EVENTFD && m
|
depends on TARGET_CORE && EVENTFD
|
||||||
select VHOST
|
select VHOST
|
||||||
default n
|
default n
|
||||||
---help---
|
---help---
|
||||||
|
|
|
@ -55,7 +55,7 @@
|
||||||
#define VHOST_SCSI_DEFAULT_TAGS 256
|
#define VHOST_SCSI_DEFAULT_TAGS 256
|
||||||
#define VHOST_SCSI_PREALLOC_SGLS 2048
|
#define VHOST_SCSI_PREALLOC_SGLS 2048
|
||||||
#define VHOST_SCSI_PREALLOC_UPAGES 2048
|
#define VHOST_SCSI_PREALLOC_UPAGES 2048
|
||||||
#define VHOST_SCSI_PREALLOC_PROT_SGLS 512
|
#define VHOST_SCSI_PREALLOC_PROT_SGLS 2048
|
||||||
|
|
||||||
struct vhost_scsi_inflight {
|
struct vhost_scsi_inflight {
|
||||||
/* Wait for the flush operation to finish */
|
/* Wait for the flush operation to finish */
|
||||||
|
|
|
@ -27,7 +27,6 @@
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/balloon_compaction.h>
|
#include <linux/balloon_compaction.h>
|
||||||
#include <linux/oom.h>
|
|
||||||
#include <linux/wait.h>
|
#include <linux/wait.h>
|
||||||
#include <linux/mm.h>
|
#include <linux/mm.h>
|
||||||
#include <linux/mount.h>
|
#include <linux/mount.h>
|
||||||
|
@ -40,13 +39,8 @@
|
||||||
*/
|
*/
|
||||||
#define VIRTIO_BALLOON_PAGES_PER_PAGE (unsigned)(PAGE_SIZE >> VIRTIO_BALLOON_PFN_SHIFT)
|
#define VIRTIO_BALLOON_PAGES_PER_PAGE (unsigned)(PAGE_SIZE >> VIRTIO_BALLOON_PFN_SHIFT)
|
||||||
#define VIRTIO_BALLOON_ARRAY_PFNS_MAX 256
|
#define VIRTIO_BALLOON_ARRAY_PFNS_MAX 256
|
||||||
#define OOM_VBALLOON_DEFAULT_PAGES 256
|
|
||||||
#define VIRTBALLOON_OOM_NOTIFY_PRIORITY 80
|
#define VIRTBALLOON_OOM_NOTIFY_PRIORITY 80
|
||||||
|
|
||||||
static int oom_pages = OOM_VBALLOON_DEFAULT_PAGES;
|
|
||||||
module_param(oom_pages, int, S_IRUSR | S_IWUSR);
|
|
||||||
MODULE_PARM_DESC(oom_pages, "pages to free on OOM");
|
|
||||||
|
|
||||||
#ifdef CONFIG_BALLOON_COMPACTION
|
#ifdef CONFIG_BALLOON_COMPACTION
|
||||||
static struct vfsmount *balloon_mnt;
|
static struct vfsmount *balloon_mnt;
|
||||||
#endif
|
#endif
|
||||||
|
@ -86,8 +80,8 @@ struct virtio_balloon {
|
||||||
/* Memory statistics */
|
/* Memory statistics */
|
||||||
struct virtio_balloon_stat stats[VIRTIO_BALLOON_S_NR];
|
struct virtio_balloon_stat stats[VIRTIO_BALLOON_S_NR];
|
||||||
|
|
||||||
/* To register callback in oom notifier call chain */
|
/* To register a shrinker to shrink memory upon memory pressure */
|
||||||
struct notifier_block nb;
|
struct shrinker shrinker;
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct virtio_device_id id_table[] = {
|
static struct virtio_device_id id_table[] = {
|
||||||
|
@ -365,38 +359,6 @@ static void update_balloon_size(struct virtio_balloon *vb)
|
||||||
&actual);
|
&actual);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* virtballoon_oom_notify - release pages when system is under severe
|
|
||||||
* memory pressure (called from out_of_memory())
|
|
||||||
* @self : notifier block struct
|
|
||||||
* @dummy: not used
|
|
||||||
* @parm : returned - number of freed pages
|
|
||||||
*
|
|
||||||
* The balancing of memory by use of the virtio balloon should not cause
|
|
||||||
* the termination of processes while there are pages in the balloon.
|
|
||||||
* If virtio balloon manages to release some memory, it will make the
|
|
||||||
* system return and retry the allocation that forced the OOM killer
|
|
||||||
* to run.
|
|
||||||
*/
|
|
||||||
static int virtballoon_oom_notify(struct notifier_block *self,
|
|
||||||
unsigned long dummy, void *parm)
|
|
||||||
{
|
|
||||||
struct virtio_balloon *vb;
|
|
||||||
unsigned long *freed;
|
|
||||||
unsigned num_freed_pages;
|
|
||||||
|
|
||||||
vb = container_of(self, struct virtio_balloon, nb);
|
|
||||||
if (!virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_DEFLATE_ON_OOM))
|
|
||||||
return NOTIFY_OK;
|
|
||||||
|
|
||||||
freed = parm;
|
|
||||||
num_freed_pages = leak_balloon(vb, oom_pages);
|
|
||||||
update_balloon_size(vb);
|
|
||||||
*freed += num_freed_pages;
|
|
||||||
|
|
||||||
return NOTIFY_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void update_balloon_stats_func(struct work_struct *work)
|
static void update_balloon_stats_func(struct work_struct *work)
|
||||||
{
|
{
|
||||||
struct virtio_balloon *vb;
|
struct virtio_balloon *vb;
|
||||||
|
@ -455,9 +417,13 @@ static int init_vqs(struct virtio_balloon *vb)
|
||||||
num_stats = update_balloon_stats(vb);
|
num_stats = update_balloon_stats(vb);
|
||||||
|
|
||||||
sg_init_one(&sg, vb->stats, sizeof(vb->stats[0]) * num_stats);
|
sg_init_one(&sg, vb->stats, sizeof(vb->stats[0]) * num_stats);
|
||||||
if (virtqueue_add_outbuf(vb->stats_vq, &sg, 1, vb, GFP_KERNEL)
|
err = virtqueue_add_outbuf(vb->stats_vq, &sg, 1, vb,
|
||||||
< 0)
|
GFP_KERNEL);
|
||||||
BUG();
|
if (err) {
|
||||||
|
dev_warn(&vb->vdev->dev, "%s: add stat_vq failed\n",
|
||||||
|
__func__);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
virtqueue_kick(vb->stats_vq);
|
virtqueue_kick(vb->stats_vq);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -546,6 +512,52 @@ static struct file_system_type balloon_fs = {
|
||||||
|
|
||||||
#endif /* CONFIG_BALLOON_COMPACTION */
|
#endif /* CONFIG_BALLOON_COMPACTION */
|
||||||
|
|
||||||
|
static unsigned long virtio_balloon_shrinker_scan(struct shrinker *shrinker,
|
||||||
|
struct shrink_control *sc)
|
||||||
|
{
|
||||||
|
unsigned long pages_to_free, pages_freed = 0;
|
||||||
|
struct virtio_balloon *vb = container_of(shrinker,
|
||||||
|
struct virtio_balloon, shrinker);
|
||||||
|
|
||||||
|
pages_to_free = sc->nr_to_scan * VIRTIO_BALLOON_PAGES_PER_PAGE;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* One invocation of leak_balloon can deflate at most
|
||||||
|
* VIRTIO_BALLOON_ARRAY_PFNS_MAX balloon pages, so we call it
|
||||||
|
* multiple times to deflate pages till reaching pages_to_free.
|
||||||
|
*/
|
||||||
|
while (vb->num_pages && pages_to_free) {
|
||||||
|
pages_to_free -= pages_freed;
|
||||||
|
pages_freed += leak_balloon(vb, pages_to_free);
|
||||||
|
}
|
||||||
|
update_balloon_size(vb);
|
||||||
|
|
||||||
|
return pages_freed / VIRTIO_BALLOON_PAGES_PER_PAGE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned long virtio_balloon_shrinker_count(struct shrinker *shrinker,
|
||||||
|
struct shrink_control *sc)
|
||||||
|
{
|
||||||
|
struct virtio_balloon *vb = container_of(shrinker,
|
||||||
|
struct virtio_balloon, shrinker);
|
||||||
|
|
||||||
|
return vb->num_pages / VIRTIO_BALLOON_PAGES_PER_PAGE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void virtio_balloon_unregister_shrinker(struct virtio_balloon *vb)
|
||||||
|
{
|
||||||
|
unregister_shrinker(&vb->shrinker);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int virtio_balloon_register_shrinker(struct virtio_balloon *vb)
|
||||||
|
{
|
||||||
|
vb->shrinker.scan_objects = virtio_balloon_shrinker_scan;
|
||||||
|
vb->shrinker.count_objects = virtio_balloon_shrinker_count;
|
||||||
|
vb->shrinker.seeks = DEFAULT_SEEKS;
|
||||||
|
|
||||||
|
return register_shrinker(&vb->shrinker);
|
||||||
|
}
|
||||||
|
|
||||||
static int virtballoon_probe(struct virtio_device *vdev)
|
static int virtballoon_probe(struct virtio_device *vdev)
|
||||||
{
|
{
|
||||||
struct virtio_balloon *vb;
|
struct virtio_balloon *vb;
|
||||||
|
@ -557,7 +569,7 @@ static int virtballoon_probe(struct virtio_device *vdev)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
vdev->priv = vb = kmalloc(sizeof(*vb), GFP_KERNEL);
|
vdev->priv = vb = kzalloc(sizeof(*vb), GFP_KERNEL);
|
||||||
if (!vb) {
|
if (!vb) {
|
||||||
err = -ENOMEM;
|
err = -ENOMEM;
|
||||||
goto out;
|
goto out;
|
||||||
|
@ -566,8 +578,6 @@ static int virtballoon_probe(struct virtio_device *vdev)
|
||||||
INIT_WORK(&vb->update_balloon_stats_work, update_balloon_stats_func);
|
INIT_WORK(&vb->update_balloon_stats_work, update_balloon_stats_func);
|
||||||
INIT_WORK(&vb->update_balloon_size_work, update_balloon_size_func);
|
INIT_WORK(&vb->update_balloon_size_work, update_balloon_size_func);
|
||||||
spin_lock_init(&vb->stop_update_lock);
|
spin_lock_init(&vb->stop_update_lock);
|
||||||
vb->stop_update = false;
|
|
||||||
vb->num_pages = 0;
|
|
||||||
mutex_init(&vb->balloon_lock);
|
mutex_init(&vb->balloon_lock);
|
||||||
init_waitqueue_head(&vb->acked);
|
init_waitqueue_head(&vb->acked);
|
||||||
vb->vdev = vdev;
|
vb->vdev = vdev;
|
||||||
|
@ -578,17 +588,10 @@ static int virtballoon_probe(struct virtio_device *vdev)
|
||||||
if (err)
|
if (err)
|
||||||
goto out_free_vb;
|
goto out_free_vb;
|
||||||
|
|
||||||
vb->nb.notifier_call = virtballoon_oom_notify;
|
|
||||||
vb->nb.priority = VIRTBALLOON_OOM_NOTIFY_PRIORITY;
|
|
||||||
err = register_oom_notifier(&vb->nb);
|
|
||||||
if (err < 0)
|
|
||||||
goto out_del_vqs;
|
|
||||||
|
|
||||||
#ifdef CONFIG_BALLOON_COMPACTION
|
#ifdef CONFIG_BALLOON_COMPACTION
|
||||||
balloon_mnt = kern_mount(&balloon_fs);
|
balloon_mnt = kern_mount(&balloon_fs);
|
||||||
if (IS_ERR(balloon_mnt)) {
|
if (IS_ERR(balloon_mnt)) {
|
||||||
err = PTR_ERR(balloon_mnt);
|
err = PTR_ERR(balloon_mnt);
|
||||||
unregister_oom_notifier(&vb->nb);
|
|
||||||
goto out_del_vqs;
|
goto out_del_vqs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -597,13 +600,19 @@ static int virtballoon_probe(struct virtio_device *vdev)
|
||||||
if (IS_ERR(vb->vb_dev_info.inode)) {
|
if (IS_ERR(vb->vb_dev_info.inode)) {
|
||||||
err = PTR_ERR(vb->vb_dev_info.inode);
|
err = PTR_ERR(vb->vb_dev_info.inode);
|
||||||
kern_unmount(balloon_mnt);
|
kern_unmount(balloon_mnt);
|
||||||
unregister_oom_notifier(&vb->nb);
|
|
||||||
vb->vb_dev_info.inode = NULL;
|
|
||||||
goto out_del_vqs;
|
goto out_del_vqs;
|
||||||
}
|
}
|
||||||
vb->vb_dev_info.inode->i_mapping->a_ops = &balloon_aops;
|
vb->vb_dev_info.inode->i_mapping->a_ops = &balloon_aops;
|
||||||
#endif
|
#endif
|
||||||
|
/*
|
||||||
|
* We continue to use VIRTIO_BALLOON_F_DEFLATE_ON_OOM to decide if a
|
||||||
|
* shrinker needs to be registered to relieve memory pressure.
|
||||||
|
*/
|
||||||
|
if (virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_DEFLATE_ON_OOM)) {
|
||||||
|
err = virtio_balloon_register_shrinker(vb);
|
||||||
|
if (err)
|
||||||
|
goto out_del_vqs;
|
||||||
|
}
|
||||||
virtio_device_ready(vdev);
|
virtio_device_ready(vdev);
|
||||||
|
|
||||||
if (towards_target(vb))
|
if (towards_target(vb))
|
||||||
|
@ -635,8 +644,8 @@ static void virtballoon_remove(struct virtio_device *vdev)
|
||||||
{
|
{
|
||||||
struct virtio_balloon *vb = vdev->priv;
|
struct virtio_balloon *vb = vdev->priv;
|
||||||
|
|
||||||
unregister_oom_notifier(&vb->nb);
|
if (virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_DEFLATE_ON_OOM))
|
||||||
|
virtio_balloon_unregister_shrinker(vb);
|
||||||
spin_lock_irq(&vb->stop_update_lock);
|
spin_lock_irq(&vb->stop_update_lock);
|
||||||
vb->stop_update = true;
|
vb->stop_update = true;
|
||||||
spin_unlock_irq(&vb->stop_update_lock);
|
spin_unlock_irq(&vb->stop_update_lock);
|
||||||
|
|
|
@ -397,9 +397,23 @@ static struct virtqueue *vm_setup_vq(struct virtio_device *vdev, unsigned index,
|
||||||
/* Activate the queue */
|
/* Activate the queue */
|
||||||
writel(virtqueue_get_vring_size(vq), vm_dev->base + VIRTIO_MMIO_QUEUE_NUM);
|
writel(virtqueue_get_vring_size(vq), vm_dev->base + VIRTIO_MMIO_QUEUE_NUM);
|
||||||
if (vm_dev->version == 1) {
|
if (vm_dev->version == 1) {
|
||||||
|
u64 q_pfn = virtqueue_get_desc_addr(vq) >> PAGE_SHIFT;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* virtio-mmio v1 uses a 32bit QUEUE PFN. If we have something
|
||||||
|
* that doesn't fit in 32bit, fail the setup rather than
|
||||||
|
* pretending to be successful.
|
||||||
|
*/
|
||||||
|
if (q_pfn >> 32) {
|
||||||
|
dev_err(&vdev->dev,
|
||||||
|
"platform bug: legacy virtio-mmio must not be used with RAM above 0x%llxGB\n",
|
||||||
|
0x1ULL << (32 + PAGE_SHIFT - 30));
|
||||||
|
err = -E2BIG;
|
||||||
|
goto error_bad_pfn;
|
||||||
|
}
|
||||||
|
|
||||||
writel(PAGE_SIZE, vm_dev->base + VIRTIO_MMIO_QUEUE_ALIGN);
|
writel(PAGE_SIZE, vm_dev->base + VIRTIO_MMIO_QUEUE_ALIGN);
|
||||||
writel(virtqueue_get_desc_addr(vq) >> PAGE_SHIFT,
|
writel(q_pfn, vm_dev->base + VIRTIO_MMIO_QUEUE_PFN);
|
||||||
vm_dev->base + VIRTIO_MMIO_QUEUE_PFN);
|
|
||||||
} else {
|
} else {
|
||||||
u64 addr;
|
u64 addr;
|
||||||
|
|
||||||
|
@ -430,6 +444,8 @@ static struct virtqueue *vm_setup_vq(struct virtio_device *vdev, unsigned index,
|
||||||
|
|
||||||
return vq;
|
return vq;
|
||||||
|
|
||||||
|
error_bad_pfn:
|
||||||
|
vring_del_virtqueue(vq);
|
||||||
error_new_virtqueue:
|
error_new_virtqueue:
|
||||||
if (vm_dev->version == 1) {
|
if (vm_dev->version == 1) {
|
||||||
writel(0, vm_dev->base + VIRTIO_MMIO_QUEUE_PFN);
|
writel(0, vm_dev->base + VIRTIO_MMIO_QUEUE_PFN);
|
||||||
|
|
|
@ -122,6 +122,7 @@ static struct virtqueue *setup_vq(struct virtio_pci_device *vp_dev,
|
||||||
struct virtqueue *vq;
|
struct virtqueue *vq;
|
||||||
u16 num;
|
u16 num;
|
||||||
int err;
|
int err;
|
||||||
|
u64 q_pfn;
|
||||||
|
|
||||||
/* Select the queue we're interested in */
|
/* Select the queue we're interested in */
|
||||||
iowrite16(index, vp_dev->ioaddr + VIRTIO_PCI_QUEUE_SEL);
|
iowrite16(index, vp_dev->ioaddr + VIRTIO_PCI_QUEUE_SEL);
|
||||||
|
@ -141,9 +142,17 @@ static struct virtqueue *setup_vq(struct virtio_pci_device *vp_dev,
|
||||||
if (!vq)
|
if (!vq)
|
||||||
return ERR_PTR(-ENOMEM);
|
return ERR_PTR(-ENOMEM);
|
||||||
|
|
||||||
|
q_pfn = virtqueue_get_desc_addr(vq) >> VIRTIO_PCI_QUEUE_ADDR_SHIFT;
|
||||||
|
if (q_pfn >> 32) {
|
||||||
|
dev_err(&vp_dev->pci_dev->dev,
|
||||||
|
"platform bug: legacy virtio-mmio must not be used with RAM above 0x%llxGB\n",
|
||||||
|
0x1ULL << (32 + PAGE_SHIFT - 30));
|
||||||
|
err = -E2BIG;
|
||||||
|
goto out_del_vq;
|
||||||
|
}
|
||||||
|
|
||||||
/* activate the queue */
|
/* activate the queue */
|
||||||
iowrite32(virtqueue_get_desc_addr(vq) >> VIRTIO_PCI_QUEUE_ADDR_SHIFT,
|
iowrite32(q_pfn, vp_dev->ioaddr + VIRTIO_PCI_QUEUE_PFN);
|
||||||
vp_dev->ioaddr + VIRTIO_PCI_QUEUE_PFN);
|
|
||||||
|
|
||||||
vq->priv = (void __force *)vp_dev->ioaddr + VIRTIO_PCI_QUEUE_NOTIFY;
|
vq->priv = (void __force *)vp_dev->ioaddr + VIRTIO_PCI_QUEUE_NOTIFY;
|
||||||
|
|
||||||
|
@ -160,6 +169,7 @@ static struct virtqueue *setup_vq(struct virtio_pci_device *vp_dev,
|
||||||
|
|
||||||
out_deactivate:
|
out_deactivate:
|
||||||
iowrite32(0, vp_dev->ioaddr + VIRTIO_PCI_QUEUE_PFN);
|
iowrite32(0, vp_dev->ioaddr + VIRTIO_PCI_QUEUE_PFN);
|
||||||
|
out_del_vq:
|
||||||
vring_del_virtqueue(vq);
|
vring_del_virtqueue(vq);
|
||||||
return ERR_PTR(err);
|
return ERR_PTR(err);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue